Indexación de matrices con enumeraciones en C #

Tengo muchas colecciones de números de tamaño fijo donde se puede acceder a cada entrada con una constante. Naturalmente, esto parece apuntar a matrices y enumeraciones:

enum StatType {
    Foo = 0,
    Bar
    // ...
}

float[] stats = new float[...];
stats[StatType.Foo] = 1.23f;

El problema con esto es, por supuesto, que no puede usar una enumeración para indexar una matriz sin una conversión (aunque el IL compilado está usando entradas simples). Entonces tienes que escribir esto por todas partes:

stats[(int)StatType.foo] = 1.23f;

He intentado encontrar formas de utilizar la misma sintaxis fácil sin conversión, pero todavía no he encontrado una solución perfecta. Usar un diccionario parece estar fuera de discusión ya que descubrí que es aproximadamente 320 veces más lento que una matriz. También intenté escribir una clase genérica para una matriz con enumeraciones como índice:

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; }
    }
}

o incluso una variante con un segundo parámetro genérico que especifica la enumeración. Esto se acerca bastante a lo que quiero, pero el problema es que no puede simplemente emitir una enumeración inespecífica (ya sea desde un parámetro genérico o el tipo de recuadro Enum) a int. En su lugar, primero debe encuadrarlo con un molde para objetar y luego devolverlo. Esto funciona, pero es bastante lento. Descubrí que la IL generada para el indexador se parece a esto:

.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 
}

Como puede ver, hay instrucciones innecesarias de caja y unbox allí. Si los elimina del binario, el código funciona bien y es un poco más lento que el acceso de matriz puro.

¿Hay alguna manera de superar fácilmente este problema? O tal vez incluso mejores maneras? Creo que también sería posible etiquetar dichos métodos de indexación con un atributo personalizado y eliminar esas dos instrucciones después de la compilación. ¿Cuál sería una biblioteca adecuada para eso? Tal vez Mono.Cecil?

Por supuesto, siempre existe la posibilidad de soltar enumeraciones y usar constantes como esta:

static class StatType {
    public const int Foo = 0;
    public const int Bar = 1;
    public const int End = 2;
}

que puede ser la forma más rápida ya que puede acceder directamente a la matriz.

Respuestas a la pregunta(7)

Su respuesta a la pregunta