2016-06-26 7 views
3

Ich habe die Notwendigkeit, ein paar Kontrollen wie dies zu tun:Wie überprüft man, ob die Klasse "ist" eine Instanz eines Typs, der als Variable in C# angegeben ist?

if(thisInstance is ThatClass || thisInstance is ThatOtherClass) 

Ich will eigentlich nicht viel davon zu tun, mehr brauchen, so konnte ich es einfach schreiben, wie es oben ist, aber ich würde bevorzugen Sie es immer noch auf eine sauberere Weise, z. wie folgt:

Type[] arrayOfClasses = new Type[] { typeof(ThatClass), typeof(ThatOtherClass))} 
if(isOfAnyType(thisInstance, arrayOfClasses)) 

Aber aus irgendeinem Grund kann ich es nicht zur Arbeit bekommen. Aus irgendeinem Grund, obwohl die Zeichenfolge Darstellungen von

thisInstance.GetType() 

und

typeof(ThatClass) 

wäre das gleiche,

thisInstance.GetType().IsInstanceOfType(type) 

wird noch immer in falschen führen.

Falls es einen Unterschied macht, ist dies ein Unity-Projekt. Wenn Sie also einen weiteren GetType() für die vergleichbaren Elemente (zB thisInstance.GetType(). GetType()) aufrufen, ist das Ergebnis immer System.MonoType, In diesem Fall gibt IsInstanceOfType immer "true" zurück, was natürlich auch nicht nützlich ist.

Irgendwelche Ideen, warum der Vergleich fehlschlägt oder wie es funktioniert? Oder sollte ich einfach aufgeben und einfach "thisInstance is ThatClass" verwenden, wo immer es nötig ist?

+1

Ich würde nicht Ihren ursprünglichen Code in irgendeiner Weise "unordentlich" sein. Es scheint sehr einfach zu sein. Warum Reflexion verwenden, wenn Sie einen Operator der Sprache verwenden können? Die bessere Frage wäre: "Kann ich meinen Code umstrukturieren, so dass die Überprüfung" "unnötig ist?" –

+0

Nun, mit nur diesen beiden Klassen ist es nicht besonders unordentlich, aber es ist weniger einfach konfigurierbar, und mit mehr Klassen würde es aus meiner Sicht ein bisschen unordentlich erscheinen. – Jeffed

+0

Sicher, aber dann ist die Frage: Warum haben Sie ein Programm, wo Sie eine Menge Laufzeitüberprüfungen des Typs einer Sache machen müssen? Anstatt zu versuchen, irgendeinen uneleganten Code, der aus den Laufzeitüberprüfungen resultiert, zu überarbeiten, versuchen Sie stattdessen, sie vollständig zu eliminieren. –

Antwort

1

Sie können issubclass verwenden:

thisInstance.GetType().IsSubclassOf(typeof(ThatClass)) 
+1

Danke für den Vorschlag. Das wird jedoch nicht funktionieren, wenn die Klasse vom selben Typ ist. – Jeffed

1

gewünschten Art und Weise bekommen Sie diese Methode könnte zur Arbeit verwenden:

public static bool IsOfAnyType(object obj, Type[] types) 
{ 
    return types.Any(type => type.IsInstanceOfType(obj)); 
} 

Wenn Sie nicht Linq verwenden können Sie die Methode so schreiben kann :

public static bool IsOfAnyType(object obj, Type[] types) 
{ 
    foreach (var type in types) 
    { 
     if (type.IsInstanceOfType(obj)) 
      return true; 
    } 
    return false; 
} 

das ich diesen Code verwendet zu testen:

Type[] typesToCheck = { typeof(ThatClass), typeof(ThatOtherClass) }; 

ThatClass input1 = new ThatClass(); 
ThatOtherClass input2 = new ThatOtherClass(); 

if (IsOfAnyType(input1, typesToCheck)) 
    Console.WriteLine("Hello world from " + input1.GetType()); 
if (IsOfAnyType(input2, typesToCheck)) 
    Console.WriteLine("Hello world from " + input2.GetType()); 
+3

'obj.GetType() == type' hat nicht das gleiche Verhalten wie' is', du brauchst 'type.IsAssignableFrom (obj.GetType())' –

+0

@ScottChamberlain Großer Vorschlag, ich habe es meiner Antwort hinzugefügt . Vielen Dank! –

+1

Cool, danke! Diese Linq-Implementierung ist unglaublich kompakt. Ich habe es früher für etwas Integration verwendet, aber ich sollte wirklich anfangen, es auf einer allgemeineren Grundlage zu verwenden. Was meiner Meinung nach ein wenig kontraintuitiv ist, ist das, was "IsInstanceOfType" tatsächlich tut. Ich hätte angenommen, dass "Katze ist Instanz von Typ Tier" wahr wäre, aber "Tier ist Instanz von Typ Katze" wäre falsch, weshalb ich in meinem Beispiel diese umgekehrt in meinem Start-Post hatte. Aber anscheinend nach den Dokumenten ist es wahr, solange "aktueller Typ in der Vererbungshierarchie ist", also funktioniert dein Vorschlag! – Jeffed

3

Sie könnten so etwas verwenden. Die Methode überprüft ein generisches Objekt, ob es einen der Typen innerhalb des Arrays enthält, und gibt ein bool zurück.

public static bool IsOfAnyType<T>(T obj, Type[] types) 
    { 
     bool isOfAnyType = false; 

     for (int i = 0; i < classes.Length; i++) 
     { 
      if (types[i].IsAssignableFrom (obj.GetType())) 
      { 
       isOfAnyType = true; 
       break; 
      } 
     } 
     return isOfAnyType; 
     }  
+0

Warum die Notwendigkeit für Generika? Alles ist bereits von "Objekt" abgeleitet. Die Verwendung von Generika scheint eine Menge unnötigen Overhead zu sein. –

+0

@MattRowland - Ich würde das Gegenteil behaupten. Wenn Sie 'object object' verwenden würden, wäre das implizite Boxing und Unboxing, während bei der Verwendung von generics das Objekt vom Typ T bleibt. In der Realität würde ich davon ausgehen, dass es sich um denselben Maschinencode handelt, egal ob Sie ein Objekt verwenden oder nicht. – pijemcolu

+0

Danke! Mit oder ohne Generika scheint IsAssignableFrom zu funktionieren! Das Seltsame ist, dass ich dachte, ich hätte das schon getestet, aber ich denke, vielleicht habe ich Dinge falsch herum gedacht und musste die beiden Typen an den falschen Stellen testen. Also auf jeden Fall Problem gelöst! – Jeffed

Verwandte Themen