我编写了一个使用System.Reflection.Emit生成IL的编译器。这适用于代码,但我不知道如何发出我需要包含的大型初始化表。编译器的重点是生成这些表,并且无法在运行时计算初始化器。
我尝试将初始化数据存储在使用Ldstr加载的字符串中,但事实证明这些字符串总共有多长时间存在硬限制。
我还尝试发出分配数组然后分配初始化程序的代码(a [0] = const0; a [1] = const1; a [2] = const2,...)。虽然只在初始化时执行一次,但这似乎可以减慢执行速度。我猜JIT编译器不像很多线性代码。
我想我可以尝试将初始化程序包含为资源文件,但我想解析它不会那么快。理想情况下,我想使用一些方法让我将所有内容存储在一个DLL中。
在.net中初始化大量数据的“常用”方法是什么?
答案 0 :(得分:3)
看看C#如何初始化值类型的静态数组。 (这可能只适用于valuetypes)。
IT在<module>
所在的 - 命名空间中创建了一个类,称为<PrivateImplementationDetails>{GUID_OF_YOUR_ASSEMBLY}
在这个类中,它创建了一个结构,用于使用以下属性初始化数组:
[StructLayout(LayoutKind.Explicit, Size=SIZE_OF_ARRAY_IN_BYTES, Pack=1)]
private struct __StaticArrayInitTypeSize=SIZE_OF_ARRAY_IN_BYTES
{
}
其中SIZE_OF_ARRAY_IN_BYTES是元素的字节数乘以数组的长度。 (例如int[] foo={0,1,2,3,4,5,6,7,8,9}
将是Size = 40)
在程序集中,它将数组的二进制表示形式分配给<PrivateImplementationDetails>
中的内部静态只读字段。
最后,它将一个运行时场句柄加载到包含数组主体的字段,并调用方法System.Runtime.CompilerServices.RuntimeHelpers.InitializeArray
不幸的是,关于这种方法的文档非常糟糕。看起来你将数组传递给它,然后将句柄传递给一个字段。我的示例静态初始化程序的IL看起来像这样,希望这有助于::
.method private hidebysig specialname rtspecialname static void .cctor() cil managed
{
.maxstack 8
L_0000: ldc.i4.s 0x15
L_0002: newarr int32
L_0007: dup
L_0008: ldtoken valuetype <PrivateImplementationDetails>{D28836D0-542D-4735-8815-954F79B1D29C}/__StaticArrayInitTypeSize=84 <PrivateImplementationDetails>{D28836D0-542D-4735-8815-954F79B1D29C}::$$method0x6000003-1
L_000d: call void [mscorlib]System.Runtime.CompilerServices.RuntimeHelpers::InitializeArray(class [mscorlib]System.Array, valuetype [mscorlib]System.RuntimeFieldHandle)
L_0012: stsfld int32[] Test.Program::vals
L_0017: ret
}