2011-07-01 6 views
5

Estoy tratando de escribir clases que manejen diferentes tipos de números. Yo sé que C# (y .Net en general, creo) no tiene interfaz INumber, así que no puedo usar algo como lo siguiente:¿Cómo puedo escribir una sola clase para compilar varias veces con diferentes tipos de números?

public class Adder<T> where T:INumber 
    { 
     public T Add(T a, T b) 
     { 
      return a + b; 
     } 
    } 

Eso está bien, sin embargo, porque me gustaría evitar el boxeo/unboxing de cada uno de mis números. Podría, sin embargo, utilizar la compilación condicional para cada tipo Quiero apoyar:

#if FLOAT 
    public class AdderF 
    { 
     public float Add(float a, float b) 
#else 
    public class Adder 
    { 
     public int Add(int a, int b) 
#endif 
     { 
      return a + b; 
     } 
    } 

Esto significa que voy a necesitar para compilar una diferente Library.dll y LibraryF.dll, sin embargo. ¿Hay alguna solución más elegante para esto?

Obviamente, en mi ejemplo, simplemente puedo escribir el código dos veces. Me gustaría utilizar este proceso, sin embargo, para crear estructuras de datos complicadas grandes con una versión entera y una versión de coma flotante, por lo que no quiero la posibilidad de errores de copiar y pegar al actualizar mi estructura. Tampoco quiero que la pérdida de velocidad abarque la estructura de coma flotante en un envoltorio integral, y que convierta innecesariamente todas las entradas al tipo de datos más indulgente.

Respuesta

3

Supongo que depende de qué tan estricto quieras que sea. ¿Desea un método Add que solo tome dos parámetros del mismo tipo (int e int, float y float) ...? De lo contrario, y el rendimiento no es muy importante, entonces puede implementar su solución con decimal y todo funcionará.

Si tiene que ser estricto, y desea versiones específicas por tipo, es posible que desee examinar la generación de código T4. Es similar a las plantillas de C++ (algunas personas piensan que las plantillas C++ y los genéricos C# son los mismos, pero no lo son).

Scott Hanselman escribió an interesting article sobre él.

+0

Como dije, estoy tratando de sacar más rendimiento de mis estructuras de datos, y no lo hago Creo que usar 'decimal's en todas partes cuando podría estar usando' int's en su lugar sería efectivo para eso. T4 es definitivamente una tecnología genial que no conocía, ¡y sin dudas lo investigaré! – dlras2

3

Quizás esto podría ser útil: Is there a C# generic constraint for "real number" types?.

Parece que no es posible directamente como usted ha dicho. Sería útil tenerlo.

+0

Gracias! Estaba buscando un enlace como ese para incluir con mi pregunta. Sé que puedo usar calculadoras abstractas como esa para trabajar con varios tipos de números, pero mi punto aquí es lograr un mayor rendimiento fuera de las estructuras enteras cuando la precisión del punto flotante no es necesaria. – dlras2

2

El principal desafío aquí es que la fluctuación de fase tiene que emitir diferentes códigos de operación dependiendo de si está agregando flotadores o ints, por lo tanto, aunque el código se ve de manera similar, en realidad es bastante diferente. Esto es factible en C++ (porque las plantillas se compilan por separado para cada definición de tipo), pero los genéricos de .NET funcionan de manera diferente. Eche un vistazo a T4 templates como una posible solución (si realmente necesita la capacidad de compilar como float o int por separado).

+0

+1 para la explicación de plantillas C++ vs. genéricos .Net, y para la sugerencia T4. – dlras2

+1

De hecho, me equivoqué un poco, ya que el compilador podría admitir una restricción de 'número' que permitiera emitir el Opcode de IL Add (en lugar de tratar de resolver un operador de 'agregar'), con jitting específico de tipo manejando las diferencias . Esto aún causaría algunas limitaciones, ya que hay una instrucción Add.Ovf separada para los enteros, por lo que solo podría admitir la adición sin la verificación de desbordamiento de enteros.El compilador también necesitaría soporte de casos especiales para entender un 'número primitivo' que aún no es un tipo específico, creando nuevos y divertidos casos límite para el Sr. Lippert. –

Cuestiones relacionadas