我有一个带有静态类的小型C#库,它包含一个非常大但简单的四维字节数组,表示一个多维决策表(总共大约90K字节)。
还有另外一个值得注意的数据结构,一个有助于索引到决策表第一维的字典。
此决策表是一个静态私有数据成员,由数组静态初始值设定项初始化。代码在Visual Studio 2010中使用T4从Excel文档生成。
决策是通过索引到多维数组的静态方法获得的。
当我使用这个库运行一个简单的测试应用程序时,它会弹出一个“System.TypeLoadException:内部限制:太多字段”。例外,在第一次调用静态决策方法时。
Stackoverflow上的one remotely related主题提到带有“太多符号”的库。我可能错了,但我的图书馆似乎确实很少有符号。
这里发生了什么?
代码段:
private static byte[][][][] decisions = new byte[][][][] {
new byte[][][] {
new byte[][] {
new byte[]{5,6,6},new byte[]{5,6,6},
new byte[]{5,6,6},new byte[]{5,6,6},new byte[]{5,6,6},
new byte[]{5,6,6},new byte[]{5,6,6},new byte[]{5,6,6},new byte[]{5,6,6},
new byte[]{5,6,6},new byte[]{5,6,6},new byte[]{5,6,6},new byte[]{5,6,6},new byte[]{5,6,6},
new byte[]{5,6,6},new byte[]{5,6,6},new byte[]{5,6,6},new byte[]{5,6,6},new byte[]{5,6,6},new byte[]{5,6,6},
new byte[]{5,6,6},new byte[]{5,6,6},new byte[]{5,6,6},new byte[]{5,6,6},new byte[]{5,6,6},new byte[]{5,6,6},new byte[]{5,6,6},
new byte[]{5,6,6},new byte[]{5,6,6},new byte[]{5,6,6},new byte[]{5,6,6},new byte[]{5,6,6},new byte[]{5,6,6},new byte[]{5,6,6},new byte[]{5,6,6},
new byte[]{5,6,6},new byte[]{5,6,6},new byte[]{5,6,6},new byte[]{5,6,6},new byte[]{5,6,6},new byte[]{5,6,6},new byte[]{5,6,6},new byte[]{5,6,6},new byte[]{5,6,6}
},
new byte[][] {
new byte[]{5,6,6},new byte[]{5,6,6},
new byte[]{5,6,6},new byte[]{5,6,6},new byte[]{5,6,6},
new byte[]{5,6,6},new byte[]{5,6,6},new byte[]{5,6,6},new byte[]{5,6,6},
new byte[]{5,6,6},new byte[]{5,6,6},new byte[]{5,6,6},new byte[]{5,6,6},new byte[]{5,6,6},
new byte[]{5,6,6},new byte[]{5,6,6},new byte[]{5,6,6},new byte[]{5,6,6},new byte[]{5,6,6},new byte[]{5,6,6},
new byte[]{5,6,6},new byte[]{5,6,6},new byte[]{5,6,6},new byte[]{5,6,6},new byte[]{5,6,6},new byte[]{5,6,6},new byte[]{5,6,6},
new byte[]{5,6,6},new byte[]{5,6,6},new byte[]{5,6,6},new byte[]{5,6,6},new byte[]{5,6,6},new byte[]{5,6,6},new byte[]{5,6,6},new byte[]{5,6,6},
new byte[]{5,6,6},new byte[]{5,6,6},new byte[]{5,6,6},new byte[]{5,6,6},new byte[]{5,6,6},new byte[]{5,6,6},new byte[]{5,6,6},new byte[]{5,6,6},new byte[]{5,6,6}
},
......等等......
答案 0 :(得分:4)
new byte [] {5,6,6}
这里的问题是初始化器{5,6,6}创建了一个静态字段。你可以用Ildasm.exe看到它。 CLR在一个类中强加了最多65535个字段。您自动生成的代码超出了它。
你将不得不以不同的方式做到这一点。想到了一个文件。
答案 1 :(得分:0)
哇。挺有趣的。我不能评论那个特定的错误(虽然我希望它实际上是太多的中间本地人),但是在某些非常类似的(基于codegen的决策引擎)我通过序列化填充数据(二进制在我的情况,但任何应该工作)。这意味着两步加载(创建obj,从文件加载)但它工作得非常好。
暂且不说: 我的构造函数足以让反射器在乱糟糟的堆中爆炸(非常终端错误),所以我感觉到你的痛苦。
答案 2 :(得分:0)
您可以尝试显式地在静态构造函数中发出代码,并直接在子数组中索引,而不是使用数组初始化器语法。这将阻止静态字段的创建,而是将所有数据设置编码为大量的IL。我不确定在一种方法中IL的数量是否有类似的限制,但我相信你会发现你是否相应地修改了T4。
看起来像是:
static MyClass()
{
decisions = new byte[N1][][][];
decisions[0] = new byte[N2][][];
....
decisions[0][0][0][0] = 5;
decisions[0][0][0][1] = 6;
decisions[0][0][0][2] = 6;
...
}