2010-09-06 17 views
6

Duplicar posible:
Define a generic that implements the + operatorCómo imponer, en un parámetro de tipo genérico C#, que algunos operadores son compatibles?

estoy trabajando recientemente en una biblioteca de clases C# aplicación de un algoritmo. El punto es que me gustaría que los usuarios de la biblioteca puedan elegir la precisión de la máquina (simple o doble) con la que debería funcionar el algoritmo, y estoy tratando de hacerlo con genéricos. Así, por ejemplo:

Algorithm<double> a = new Algorithm<double>(); 
    /** Some initializations here */ 
    double result = a.Solve(); 

o

Algorithm<float> a = new Algorithm<float>(); 
    /** Some initializations here */ 
    float result = a.Solve(); 

Por lo tanto, el parámetro de tipo para las clases genéricas está destinado a ser un número decimal (porque en el código del algoritmo que necesito para usar +, *, /, -), pero no sé qué tipo de restricción de tipo imponerle. He pensado en construir una interfaz con todos los operadores pero, desafortunadamente, esto no está permitido. ¿Algunas ideas?

De lo contrario, ¿es posible obtener en C# algo similar a template specialization en C++?

Gracias

Tommaso

Respuesta

7

No se puede, básicamente. El sistema de tipo CLR no admite ese tipo de restricción.

He escrito un blog anterior acerca de cómo podría describir tales restricciones usando "static interfaces" pero no sé de ningún plan para hacer algo similar.

Es posible que desee ver el MiscUtil generic operator support lo que permitirá utilizar los operadores - pero usted tiene que utilizar una restricción de poco struct o algo por el estilo, lo que, por supuesto, permitir cosas como Guid que Don no quiero

+0

Otra posibilidad, en lugar de definir las interfaces y las clases que las implementan, debería ser capaz de declarar las interfaces y enumerar las clases que las implementan en la declaración de la interfaz. El compilador debería encargarse del resto – devio

+0

@devio: suena como una variante interesante. ¿Puedes dar algunas referencias? – tunnuz

+0

@tunnuz no hay "referencia", es un deseo, como la idea de Jon, y debería estar en la lista de deseos de alguien para la próxima versión de C#;) – devio

0

Se puede usar una solución: definir un método para cada tipo que desea suport

private static Add(float a, float b) 
{return a+b;} 
private static Add(double a, double b) 
{return a+b;} 
... 

y crear un delegado para la correcta en tiempo de ejecución:

MethodInfo addMethod=this.GetType().GetMethod("Add",BindingFlags.NotPublic|Static,null,new Type[2]{typeof(T),typeof(T)},null); 
Func<T,T,T> addFunction=(Func<T,T,T>)Delegate.CreateDelegate(typeof(Func<T,T,T>),addMethod); 
0

Esto es generalmente un serio y fugly hack, pero puede crear una clase genérica "contenedora" para los tipos numéricos que expone las operaciones que necesita y evita la creación de instancias utilizando un tipo de valor no soportado (es decir char) y luego especifique que el parámetro de tipo genérico de su algoritmo debe ser la clase contenedora.

Me gusta la solución que Floste planteó en todos los aspectos, excepto la duplicación de código. Incluso podrías hacerlo más simple; especifique sobrecargas de métodos privados, luego un método público genérico que simplemente llame al método privado, y el tiempo de ejecución seleccionará el correcto (asegúrese de incluir un catch-all que arroje una NotImplementedException).

Cuestiones relacionadas