2011-12-18 10 views
18

¿Hay alguna manera de declarar una función genérica que el tipo genérico sea de tipo 1 o type2?Método genérico donde T es type1 o type2

ejemplo:

public void Foo<T>(T number) 
{ 
} 

¿Puedo restricción de T a ser int o largo

+1

[Restricciones de Tipo Parámetros (Guía de programación C#)] (http://msdn.microsoft.com/en-us/library/d5x73970.aspx) –

+0

@BoltClock, Porque mi código se rompe cuando el parámetro no es uno de los primitivos (int, largo, doble ...) y quiero obtener errores en la compilación, no en RunTime – gdoron

+0

Relacionado: [Método genérico múltiple (OR) restricción de tipo] (http://stackoverflow.com/q/10833918) –

Respuesta

12

Puede usar generic constraints para limitar el tipo de cada argumento genérico. Lamentablemente, no existe una restricción genérica que le permita hacer cumplir en tiempo de compilación si T es type1 or type2. No hay forma de hacer cumplir en tiempo de compilación que su argumento genérico puede ser de cualquier tipo primitivo (int, long, double, ...).

7

Eso no tiene sentido; T no tendría ningún tipo utilizable en tiempo de compilación en el método.

En su lugar, debe hacer dos métodos sobrecargados.

+3

Creo que tiene sentido. Tengo un código que si pasa un parámetro diferente, entonces doble, decimal, flotante, int, largo, etc. 'se frenará. Quiero verificar esto en la compilación. No tiene sentido? – gdoron

+0

@gdoron: desde su punto de vista, tiene sentido. Desde el punto de vista del compilador, no tiene sentido, ya que 'T' no sería un tipo utilizable. – SLaks

+0

En este caso, el compilador puede tratar 'T' como el común de tipo1 y tipo2, donde no hay relación' T' es 'objeto' ... – gdoron

0

No creo que esto sea posible actualmente.

This question sobre la creación de una biblioteca matemática cubre el mismo terreno, e incluye algunas soluciones alternativas.

4

Use métodos sobrecargados en su lugar:

public void Foo(int number) 
{ 
} 

public void Foo(long number) 
{ 
} 

no puede realizar operaciones aritméticas sobre los tipos genéricos de todas formas. Tenga en cuenta que puede pasar un valor int a un parámetro long. Se convertirá automáticamente al long. Tener un solo método con un parámetro long podría ser suficiente.

Los lenguajes de programación antiguos funcionaban después del principio "Solo puede haber uno". C# le permite tener varios métodos con el mismo nombre en la misma clase, interfaz o estructura. Estos métodos deben tener una firma diferente. Esto significa que deben tener un número diferente de parámetros o parámetros con diferentes tipos (o ambos). Esto se llama sobrecarga de método.

+0

No puedo escribir 20 métodos para cada tipo de valor numérico. esto es lo que ** genéricos ** debería tener ** resuelto – gdoron

+0

Las operaciones artihméticas no son compatibles con los parámetros de tipo genérico. Ver 'System.Text.StringBuilder' para ver un ejemplo. Define más de 20 sobrecargas 'Append()' para diferentes tipos. –

0

Sé que esta es una pregunta antigua, y esto no responde perfectamente, pero puedes hacerlo con un solo método, en lugar de crear múltiples o usar restricciones genéricas ... especialmente útil si tienes 20 impar tipos para verificar

Obviamente usted no consigue el tipo compilador de comprobación como lo hace cuando se utiliza una restricción, pero esto puede ayudar en ciertas circunstancias ...

public void MyMethod<T>() 
{ 
    if (!typeof(T).Equals(typeof(int)) && 
     !typeof(T).Equals(typeof(long))) 
      throw new Exception("T must be int or long"); 

    //your logic here 
} 
0

También tuve este problema y creo que he encontrado una mejor solución (suponiendo que una versión sobrecargada de su método es insuficiente):

Mezclar Type1 y Type2 sin ningún paralelismo no tiene ningún sentido, como ya se ha escrito. Entonces tiene que haber cualquier método o propiedad accedido para ambos tipos de objetos.Para asegurarse de que el compilador que estos métodos o propiedades están disponibles para su objeto, grupo Type1 y Type2 mediante la creación de una interfaz MyInterface y su aplicación por Type1 y Type2:

interface MyInterface { 
    void MyCommonMethod(); 
    bool MyCommonProperty { get; } 
} 

class Type1 : MyInterface { 
    void MyCommonMethod() { 
    // TODO: Implement it for Type1 
    } 

    bool MyCommonProperty { 
    get { 
    // TODO: Implement it for Type1 
    } 
    } 
} 

class Type2 : MyInterface { 
    void MyCommonMethod() { 
    // TODO: Implement it for Type2 
    } 

    bool MyCommonProperty { 
    get { 
    // TODO: Implement it for Type2 
    } 
    } 
} 

Ahora, para volver a escribir el método de Foo a aceptar tanto Type1 y Type2, restricción T a ser un objeto MyInterface:

public void Foo<T>(T number) where T : MyInterface 
{ 
    throw new NotImplementedException(); 
} 

I ABATIDA esto podría ser útil. :)

6

Para ReferenceType objetos que se pueden hacer

public void DoIt<T>(T someParameter) where T : IMyType 
{ 

} 

...

public interface IMyType 
{ 
} 

public class Type1 : IMyType 
{ 
} 

public class Type2 : IMyType 
{ 
} 

Para su caso utilizando siempre y cuando el parámetro limitará el uso de enteros largos y de todos modos.

public void DoIt(long someParameter) 
{ 

} 

para limitar a ningún tipo de valor (como: int, double, corta, decimales) que puede utilizar:

public void DoIt<T>(T someParameter) where T : struct 
{ 

} 

para más información se puede consultar la documentación oficial here

Cuestiones relacionadas