我有很多固定大小的数字集合,其中每个条目都可以使用常量访问。自然,这似乎指向数组和枚举:
enum StatType {
Foo = 0,
Bar
// ...
}
float[] stats = new float[...];
stats[StatType.Foo] = 1.23f;
这样做的问题当然是您不能使用枚举来索引没有强制转换的数组(尽管编译的 IL 使用纯整数)。所以你必须到处写这个:
stats[(int)StatType.foo] = 1.23f;
我试图找到在不强制转换的情况下使用相同简单语法的方法,但还没有找到完美的解决方案。使用字典似乎是不可能的,因为我发现它比数组慢大约 320 倍。我还尝试为以枚举为索引的数组编写一个泛型类:
public sealed class EnumArray<T>
{
private T[] array;
public EnumArray(int size)
{
array = new T[size];
}
// slow!
public T this[Enum idx]
{
get { return array[(int)(object)idx]; }
set { array[(int)(object)idx] = value; }
}
}
甚至是带有指定枚举的第二个通用参数的变体。这与我想要的非常接近,但问题是您不能只将非特定枚举(无论是来自泛型参数还是盒装类型枚举)强制转换为 int。相反,您必须先将其与对象的转换相结合,然后再将其转换回。这有效,但速度很慢。我发现为索引器生成的 IL 看起来像这样:
.method public hidebysig specialname instance !T get_Item(!E idx) cil managed
{
.maxstack 8
L_0000: ldarg.0
L_0001: ldfld !0[] EnumArray`2<!T, !E>::array
L_0006: ldarg.1
L_0007: box !E
L_000c: unbox.any int32
L_0011: ldelem.any !T
L_0016: ret
}
如您所见,那里有不必要的装箱和拆箱说明。如果将它们从二进制文件中剥离出来,代码就可以正常工作,并且比纯数组访问慢一点。
有什么方法可以轻松克服这个问题吗?或者甚至更好的方法?我认为也可以使用自定义属性标记此类索引器方法并在编译后剥离这两个指令。什么是合适的图书馆?也许是 Mono.Cecil?
当然,总是有可能删除枚举并使用如下常量:
static class StatType {
public const int Foo = 0;
public const int Bar = 1;
public const int End = 2;
}
这可能是最快的方法,因为您可以直接访问数组。