2010-01-05 25 views

Respuesta

76

Sí:

if (typeof(T) == typeof(MyClass)) 
{ 
    MyClass mc = (MyClass)(object) t; 
} 
else if (typeof(T) == typeof(List<MyClass>)) 
{ 
    List<MyClass> lmc = (List<MyClass>)(object) t; 
} 

Es un poco extraño que tiene que ir a través de un molde para objetar, pero así es como funcionan los genéricos: no hay tantas conversiones de un tipo genérico como cabría esperar.

Por supuesto, otra alternativa es utilizar el proceso normal tiempo de ejecución:

MyClass mc = t as MyClass; 
if (mc != null) 
{ 
    // ... 
} 
else 
{ 
    List<MyClass> lmc = t as List<MyClass>; 
    if (lmc != null) 
    { 
     // ... 
    } 
} 

que se comportan de manera diferente al primer bloque de código si t es nulo, por supuesto.

Me intento para evitar este tipo de código siempre que sea posible, sin embargo - que puede ser necesario a veces, pero la idea de métodos genéricos es ser capaz de escribir genérico código que funciona de la misma manera para cualquier tipo .

+0

De hecho, tengo un problema un poco más complicado. ¿Qué pasa si MyClass se deriva de MyBaseClass y hay muchas más MyClasses que derivan de MyBaseClass? – synergetic

+1

@synergetic: describió la jerarquía de tipos, pero no lo que quiere hacer con ella. Puede usar la reflexión (por ejemplo, 'typeof (T) .BaseType' o' typeof (T) .IsAssignableFrom (...) 'para explorar la jerarquía de tipos si es útil. De todos modos, intentaré evitarla si fuera posible :) –

+0

Odio ser una toalla mojada aquí, pero esta respuesta se queda corta en los casos en que T es en realidad un tipo en caja (por ejemplo, objeto en caja Mi Clase = nueva MyClass()). En casos como este, el tipo devuelto por el operador typeof será objeto, no MyClass, lo que hará que falle el tipo de verificación anterior. En mi opinión, aquí es donde C# se queda corto como un lenguaje: lidiando tanto con la verificación ontológica genérica como con la lógica ontológica compleja (ej. No hay forma de decir algo como "una Vida es Mamífero y no Oso" en C# sin entrar en reflexión) – rmiesen

2

Creo que hay algo mal en su diseño. Quiere comparar tipos en un método ya genérico. Los genéricos están destinados a tratar la situación de tipo variable. recomiendo hacerlo de esta manera ..

//Generic Overload 1 
public void DoSomething<T>(T t) 
    where T : MyClass 
{ 
    ... 
} 

//Generic Overload 2 
public void DoSomething<T>(T t) 
    where T : List<MyClass> 
{ 
    ... 
} 
+0

Para el caso, solo puede soltar los genéricos y especificar el tipo de su parámetro. Pero +1 porque quería tener un polimorfismo sin parámetros. – Grault

+6

¿Cómo funciona esto exactamente? Como se señala aquí http://stackoverflow.com/questions/15367032/member-with-the-same-signature-already-defined-with-different-type-constraints "no se puede sobrecargar mediante restricciones genéricas". – Miebster

5

Es 2017 y tenemos ahora C# 7 con la coincidencia de patrones. Si su tipo T hereda object se puede codificar como esto

void Main() 
{ 
    DoSomething(new MyClass { a = 5 }); 
    DoSomething(new List<MyClass> { new MyClass { a = 5 }, new MyClass { a = 5 }}); 
} 


public void DoSomething(object t) 
{ 
    switch (t) 
    { 
     case MyClass c: 
      Console.WriteLine($"class.a = {c.a}"); 
      break; 
     case List<MyClass> l: 
      Console.WriteLine($"list.count = {l.Count}"); 
      break; 
    } 
} 

class MyClass 
{ 
    public int a { get; set;} 
} 
Cuestiones relacionadas