2009-08-24 11 views
6

Estoy tratando de realizar algún tipo de manipulación genérica independiente del tipo de número. Sin embargo, no conozco ninguna forma de usar genéricos para hacer esto. La primera idea fue filtrar los tipos entrantes con una instrucción where, pero todos los tipos de números están cerrados y, por lo tanto, no son válidos para un filtro genérico. Además, los genéricos no permiten operaciones numéricas estándar (adición, desplazamiento, etc.), por lo que la única solución que se me ocurre es volver a escribir cada método de forma no genérica. ¿Alguna otra idea?C#: Interfaz genérica para números

Como referencia, que sigue es el código que en un principio traté:

private const int BYTE_SIZE = 8; 

    private const int UINT16_SIZE = 16; 

    private const int UINT32_SIZE = 32; 

    private const int UINT64_SIZE = 64; 

    public static byte[] ToBytes(UInt16[] pnaValues) 
    { 
     return ToSmaller<byte, UInt16>(pnaValues, BYTE_SIZE, UINT16_SIZE); 
    } 

    public static byte[] ToBytes(UInt32[] pnaValues) 
    { 
     return ToSmaller<byte, UInt32>(pnaValues, BYTE_SIZE, UINT32_SIZE); 
    } 

    .... 

    public static UInt16[] ToUInt16s(byte[] pnaValues) 
    { 
     return ToLarger<UInt16, byte>(pnaValues, UINT16_SIZE, BYTE_SIZE); 
    } 

    public static UInt16[] ToUInt16s(UInt32[] pnaValues) 
    { 
     return ToSmaller<UInt16, UInt32>(pnaValues, UINT16_SIZE, UINT32_SIZE); 
    } 

    ... 

    public static UInt64[] ToUInt64s(UInt32[] pnaValues) 
    { 
     return ToLarger<UInt64, UInt32>(pnaValues, UINT64_SIZE, UINT32_SIZE); 
    } 

    private static TLarger[] ToLarger<TLarger, TSmaller>(TSmaller[] pnaSmaller, int pnLargerSize, int pnSmallerSize) 
     where TLarger : byte, UInt16, UInt32, UInt64 
     where TSmaller : byte, UInt16, UInt32, UInt64 
    { 
     TLarger[] lnaRetVal = null; 
     int lnSmallerPerLarger = pnLargerSize/pnSmallerSize; 

     System.Diagnostics.Debug.Assert((pnLargerSize % pnSmallerSize) == 0); 

     if (pnaSmaller != null) 
     { 
      System.Diagnostics.Debug.Assert((pnaSmaller % lnSmallerPerLarger) == 0); 

      lnaRetVal = new TLarger[pnaSmaller.Length/lnSmallerPerLarger]; 

      for (int i = 0; i < lnaRetVal.Length; i++) 
      { 
       lnaRetVal[i] = 0; 

       for (int j = 0; j < lnSmallerPerLarger; j++) 
       { 
        lnaRetVal[i] = (lnaRetVal[i] << pnLargerSize) + pnaSmaller[i * lnSmallerPerLarger + j]; 
       } 
      } 
     } 

     return lnaRetVal; 
    } 

    private static TSmaller[] ToSmaller<TSmaller, TLarger>(TLarger[] pnaLarger, int pnSmallerSize, int pnLargerSize) 
     where TSmaller : byte, UInt16, UInt32, UInt64 
     where TLarger : byte, UInt16, UInt32, UInt64 
    { 
     TSmaller[] lnaRetVal = null; 
     int lnSmallerPerLarger = pnLargerSize/pnSmallerSize; 

     System.Diagnostics.Debug.Assert((pnLargerSize % pnSmallerSize) == 0); 

     if (pnaSmaller != null) 
     { 
      lnaRetVal = new TSmaller[pnaLarger.Length * lnSmallerPerLarger]; 

      for (int i = 0; i < lnaRetVal.Length; i++) 
      { 
       for (int j = 0; j < lnSmallerPerLarger; j++) 
       { 
        lnaRetVal[i * lnSmallerPerLarger + (lnSmallerPerLarger - 1 - j)] 
         = pnaLarger[i] >> (j * pnLargerSize); 
       } 
      } 
     } 

     return lnaRetVal; 
    } 

Respuesta

11

No hay ninguna interfaz común para las operaciones aritméticas aplicadas por los tipos numéricos. Generic operators podría ayudar a resolver su problema.

+4

En particular para este caso, 'Operator.Convert (valor de TFrom)' puede ser útil. –

+0

Tenga en cuenta que no implementé 'LeftShift' y' RightShift', pero sería trivial agregarlo. –

0

La reescritura es probablemente la más fácil. La única otra solución que se me ocurre es ir más allá de las plantillas, escribir una Cadena que represente tu función, con caracteres de posición para el tipo, luego reemplazarla con cada nombre de tipo y compilarla en tiempo de ejecución.

Además del golpe de rendimiento inicial debido a la compilación, también será difícil llamar a estas funciones.

+0

Portando 'eval()' a C#? ¡Diablos no! :) –

Cuestiones relacionadas