注释
本文特定于 .NET Framework。 它不适用于 .NET 的较新版本实现,包括 .NET 6 及更高版本。
激活 openGenericCERCall 托管调试助手,警告根方法中具有泛型类型变量的约束执行区域(CER)图形正在 JIT 编译或本机映像生成时进行处理,并且至少一个泛型类型变量是对象引用类型。
症状
在中止线程或卸载应用程序域时,CER 代码不会运行。
原因
在 JIT 编译时,包含对象引用类型的实例化只是因为共享结果代码而具有代表性,并且每个对象引用类型变量可能是任何对象引用类型。 这可以防止提前准备某些运行时资源。
具体而言,具有泛型类型变量的方法可以在后台延迟分配资源。 这些条目称为泛型字典条目。 例如,对于泛T型类型变量的语句List<T> list = new List<T>();,运行时必须查找并可能创建运行时的确切实例化,例如List<Object>, List<String>,等等。 由于开发人员控制之外的各种原因(例如内存不足),这可能会失败。
此 MDA 只能在 JIT 编译时激活,而不是当存在确切实例化时。
激活此 MDA 时,可能的症状是 CER 不适用于不良实例化。 事实上,运行时未尝试在导致 MDA 激活的情况下实现 CER。 因此,如果开发人员使用 CER 的共享实例化,则不会捕获预期 CER 区域内的 JIT 编译错误、泛型类型加载错误或线程中止。
决议
不要对可能包含 CER 的方法使用属于对象引用类型的泛型类型变量。
对运行时的影响
此 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 runtime prior to execution.
method name="GenericMethodWithCer"
declaringType name="OpenGenericCERCall"
配置
<mdaConfig>
<assistants>
<openGenericCERCall/>
</assistants>
</mdaConfig>
Example
不执行 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 runtime.
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.");
}
}
}