2010-01-05 5 views

Répondre

76

Oui:

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

Il est un peu étrange que vous devez passer par un casting objecter, mais c'est exactement comme ça que fonctionnent les génériques - il n'y a pas autant de conversions à partir d'un type générique que l'on pourrait s'y attendre.

Bien sûr une autre alternative est d'utiliser le contrôle du temps d'exécution normale:

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

Cela se comportent différemment au premier bloc de code si t est nul, bien sûr.

Je essayer d'éviter ce genre de code lorsque cela est possible, cependant - il peut être parfois nécessaire, mais l'idée de méthodes génériques est d'être capable d'écrire code générique qui fonctionne de la même manière pour tout type .

+0

J'ai en fait un problème un peu plus compliqué. Que se passe-t-il si MyClass provient de MyBaseClass et qu'il y a beaucoup plus de MyClasses qui proviennent toutes de MyBaseClass? – synergetic

+1

@synergetic: Vous avez décrit la hiérarchie des types, mais pas ce que vous voulez en faire. Vous pouvez utiliser la réflexion (par exemple 'typeof (T) .BaseType' ou' typeof (T) .IsAssignableFrom (...) 'pour explorer la hiérarchie des types si cela est utile, mais j'essaierais quand même de l'éviter si possible :) –

+0

Hate pour être une serviette humide ici, mais cette réponse est insuffisante dans les cas où T est en fait un type encadré (ex: object boxedMyClass = new MyClass()). Dans ce cas, le type renvoyé par l'opérateur typeof sera objet, pas MyClass, ce qui entraînera l'échec de la vérification de type ci-dessus. À mon avis, c'est là que C# est un langage: traitant à la fois du filtrage de type générique et de la logique ontologique complexe (par exemple, il n'y a pas moyen de dire quelque chose comme «Mammal and Bear»).). – rmiesen

2

Je crois qu'il y a quelque chose qui cloche dans votre conception. Vous souhaitez comparer les types dans une méthode déjà générique. Les génériques sont destinés à traiter une situation de type variable. Je recommande de le faire de cette façon ..

//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

D'ailleurs, vous pouvez simplement laisser tomber les génériques et spécifier le type de votre paramètre. Mais +1 parce que je voulais avoir un polymorphisme sans paramètres. – Grault

+6

Comment cela fonctionne-t-il exactement? Comme indiqué ici http://stackoverflow.com/questions/15367032/member-with-the-same-signature-already-defined-with-different-type-constraints "vous ne pouvez pas surcharger par des contraintes génériques". – Miebster

5

Il est 2017 et nous avons maintenant C# 7 avec correspondance de motif. Si votre type T Hériter object vous pouvez vous le code comme ceci

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;} 
} 
Questions connexes