2010-01-05 16 views

Antwort

76

Ja:

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 ist etwas seltsam, dass Sie über eine Besetzung gehen müssen zu widerlegen, aber das ist nur die Art, wie Generika funktionieren - es gibt nicht so viele Konvertierungen von einem generischen Typ, wie Sie vielleicht erwarten.

Natürlich eine andere Alternative ist die normale Ausführungszeit Prüfung zu verwenden:

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

, die unterschiedlich zu dem ersten Codeblock verhalten wird, wenn t null ist, natürlich.

würde ich versuchen, diese Art von Code, wenn möglich, jedoch zu vermeiden - es manchmal notwendig sein kann, aber die Idee von generischen Methoden in der Lage seine generic Code zu schreiben, die für jede Art die gleiche Weise funktioniert .

+0

Ich habe eigentlich ein etwas komplizierteres Problem. Was ist, wenn MyClass von MyBaseClass abgeleitet ist und es viele weitere MyClasses gibt, die alle von MyBaseClass abgeleitet sind? – synergetic

+1

@synergetic: Sie haben die Typhierarchie beschrieben, aber nicht, was Sie damit machen wollen. Sie können reflection (zB 'typeof (T) .BaseType' oder' typeof (T) .IsAssignableFrom (...) 'verwenden, um die Typhierarchie zu untersuchen, wenn das nützlich ist. Ich würde es trotzdem versuchen, wenn es möglich ist :) –

+0

Hasse hier ein nasses Handtuch, aber diese Antwort ist unzureichend, wenn T tatsächlich ein Boxed-Typ ist (zB: object boxedMyClass = new MyClass()). In solchen Fällen ist der vom Operator typeof zurückgegebene Typ ein Objekt, nicht MyClass, was dazu führt, dass der obige Typ der Überprüfung fehlschlägt. Meiner Meinung nach ist dies der Punkt, an dem C# als Sprache zu kurz kommt: Es geht sowohl um generische Typüberprüfung als auch um komplexe ontologische Logik (z. B. kann man in C# nicht so etwas sagen wie "aLifeform ist Säugetier und nicht Bär")). – rmiesen

2

Ich glaube, es ist etwas falsch in Ihrem Design. Sie möchten zwischen Typen in einer bereits generischen Methode vergleichen. Generika sollen sich mit typenvariablen Situationen befassen. Ich empfehle es auf diese Weise zu tun ..

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

Zu diesem Zweck können Sie einfach die Generika löschen und den Typ des Parameters angeben. Aber +1, weil ich Polymorphie ohne Parameter haben wollte. – Grault

+6

Wie genau funktioniert das? Wie hier http://stackoverflow.com/questions/15367032/member-with-the-same-signature-ready-defined-with-different-type-constraints "kann man nicht durch generische Constraints überladen". – Miebster

5

Es ist 2017, und wir haben jetzt C# 7 mit Pattern-Matching. Wenn Ihr Typ T vererben object Sie Sie dieses

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;} 
} 
Verwandte Themen