openGenericCERCall MDA

注意

本文特定于 .NET Framework。 它不适用于 .NET 的较新版本实现,包括 .NET 6 及更高版本。

激活 openGenericCERCall 托管调试助手,警告根方法中具有通用类型变量的约束执行区域 (CER) 图形正于 JIT 编译或生成本机图像时进行处理,并且至少一个通用类型变量是对象引用类型。

症状

线程中止或应用程序域卸载时 CER 代码不运行。

原因

在 JIT 编译时,包含对象引用类型的实例只是代表性的,因为生成的代码是共享的,每个对象引用类型变量可能是任何对象引用类型。 这会阻止提前准备一些运行时资源。

特别是,使用通用类型变量的方法会在后台怠缓地分配资源。 这些被称为通用字典条目。 例如,对于语句 List<T> list = new List<T>();,其中 T 是通用类型变量,运行时必须查找并尽可能在运行时创建准确的实例化,如 List<Object>, List<String> 等。 这可能由于超出开发人员控制外的各种原因(例如内存不足)而失败。

仅应在 JIT 编译时激活此 MDA,而非有精确的实例化时激活。

此 MDA 激活时,可能的症状是 CER 对于不良实例化无法正常运行。 事实上,运行时还没尝试在导致此 MDA 被激活的情况下实现 CER。 因此,如果开发人员使用共享 CER 实例化,则不会捕获 JIT 编译错误、泛型类型加载错误或预期 CER 区域内的线程中止。

解决方法

不要对可能包含 CRE 的方法使用对象引用类型的通用类型变量。

对运行时的影响

此 MDA 对 CLR 无任何影响。

输出

下面提供了此 MDA 的输出示例:

Method 'GenericMethodWithCer', which contains at least one constrained execution region, cannot be prepared automatically since it has one or more unbound generic type parameters.
The caller must ensure this method is prepared explicitly at run time prior to execution.
method name="GenericMethodWithCer"
declaringType name="OpenGenericCERCall"

Configuration

<mdaConfig>
  <assistants>
    <openGenericCERCall/>
  </assistants>
</mdaConfig>

示例

CER 代码未执行。

using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;

class Program
{
    static void Main(string[] args)
    {
        CallGenericMethods();
    }
    static void CallGenericMethods()
    {
        // This call is correct. The instantiation of the method
        // contains only nonreference types.
        MyClass.GenericMethodWithCer<int>();

        // This call is incorrect. A shared version of the method that
        // cannot be completely analyzed will be JIT-compiled. The
        // MDA will be activated at JIT-compile time, not at run time.
        MyClass.GenericMethodWithCer<String>();
    }
}

class MyClass
{
    public static void GenericMethodWithCer<T>()
    {
        RuntimeHelpers.PrepareConstrainedRegions();
        try
        {

        }
        finally
        {
            // This is the start of the CER.
            Console.WriteLine("In finally block.");
        }
    }
}

请参阅