414 Stimmen

Wie prüfe ich, ob ein Typ ein Subtyp ODER der Typ eines Objekts ist?

Um zu überprüfen, ob ein Typ eine Unterklasse eines anderen Typs in C# ist, ist es einfach:

typeof (SubClass).IsSubclassOf(typeof (BaseClass)); // returns true

Dies wird jedoch scheitern:

typeof (BaseClass).IsSubclassOf(typeof (BaseClass)); // returns false

Gibt es eine Möglichkeit zu überprüfen, ob ein Typ entweder eine Unterklasse ODER der Basisklasse selbst ist, ohne eine OR Operator oder eine Erweiterungsmethode verwenden?

624voto

Lasse V. Karlsen Punkte 364542

Offensichtlich nicht.

Hier sind die Optionen:

Type.IsSubclassOf

Wie Sie bereits herausgefunden haben, funktioniert dies nicht, wenn die beiden Typen gleich sind, hier ein Beispiel LINQPad Programm, das demonstriert:

void Main()
{
    typeof(Derived).IsSubclassOf(typeof(Base)).Dump();
    typeof(Base).IsSubclassOf(typeof(Base)).Dump();
}

public class Base { }
public class Derived : Base { }

Ausgabe:

True
False

Dies bedeutet, dass Derived ist eine Unterklasse von Base sondern dass Base ist (offensichtlich) nicht eine Unterklasse von sich selbst.

Type.IsAssignableFrom

Dies wird Ihre Frage beantworten, aber es wird Ihnen auch falsch positive Ergebnisse liefern. Wie Eric Lippert in den Kommentaren dargelegt hat, gibt die Methode zwar tatsächlich True für die beiden oben genannten Fragen, gibt sie auch True für diese, was Sie wahrscheinlich nicht wollen:

void Main()
{
    typeof(Base).IsAssignableFrom(typeof(Derived)).Dump();
    typeof(Base).IsAssignableFrom(typeof(Base)).Dump();
    typeof(int[]).IsAssignableFrom(typeof(uint[])).Dump();
}

public class Base { }
public class Derived : Base { }

Hier erhalten Sie die folgende Ausgabe:

True
True
True

Die letzte True würde darauf hindeuten, wenn die Methode nur die gestellte Frage beantwortet hat, dass uint[] erbt von int[] oder dass es sich um den gleichen Typ handelt, was eindeutig nicht der Fall ist.

Also IsAssignableFrom ist auch nicht ganz korrekt.

is y as

Das "Problem" mit is y as im Zusammenhang mit Ihrer Frage ist, dass Sie mit den Objekten operieren und einen der Typen direkt in den Code schreiben müssen, und nicht mit Type Objekte.

Mit anderen Worten: Es lässt sich nicht kompilieren:

SubClass is BaseClass
^--+---^
   |
   +-- need object reference here

Und das hier auch nicht:

typeof(SubClass) is typeof(BaseClass)
                    ^-------+-------^
                            |
                            +-- need type name here, not Type object

Und das hier auch nicht:

typeof(SubClass) is BaseClass
^------+-------^
       |
       +-- this returns a Type object, And "System.Type" does not
           inherit from BaseClass

Schlussfolgerung

Obwohl die oben genannten Methoden für Ihre Bedürfnisse geeignet sein könnten, ist die einzig richtige Antwort auf Ihre Frage (so wie ich sie sehe), dass Sie eine zusätzliche Prüfung benötigen:

typeof(Derived).IsSubclassOf(typeof(Base)) || typeof(Derived) == typeof(Base);

was natürlich in einer Methode mehr Sinn macht:

public bool IsSameOrSubclass(Type potentialBase, Type potentialDescendant)
{
    return potentialDescendant.IsSubclassOf(potentialBase)
           || potentialDescendant == potentialBase;
}

43voto

Marc Gravell Punkte 970173
typeof(BaseClass).IsAssignableFrom(unknownType);

12voto

Thomas Punkte 62314

Sie sollten versuchen Type.IsAssignableFrom stattdessen.

1voto

Bruno Serrano Punkte 545

Wenn Sie versuchen, dies in einem Xamarin Forms PCL-Projekt zu tun, werden die oben genannten Lösungen mit IsAssignableFrom ergibt einen Fehler:

Fehler: 'Type' enthält keine Definition für 'IsAssignableFrom' und keine Erweiterungsmethode 'IsAssignableFrom', die ein erstes Argument vom Typs 'Type' gefunden werden (fehlt eine using-Anweisung oder ein Assembly-Referenz?)

denn IsAssignableFrom fragt nach einem TypeInfo Objekt. Sie können das GetTypeInfo() Methode von System.Reflection :

typeof(BaseClass).GetTypeInfo().IsAssignableFrom(typeof(unknownType).GetTypeInfo())

0voto

baskren Punkte 746

Ich poste diese Antwort in der Hoffnung, dass mir jemand mitteilt, ob und warum es eine schlechte Idee wäre. In meiner Anwendung habe ich eine Eigenschaft von Type, die ich überprüfen möchte, um sicher zu sein, dass sie typeof(A) oder typeof(B) ist, wobei B eine von A abgeleitete Klasse ist:

public class A
{
}

public class B : A
{
}

public class MyClass
{
    private Type _helperType;
    public Type HelperType
    {
        get { return _helperType; }
        set 
        {
            var testInstance = (A)Activator.CreateInstance(value);
            if (testInstance==null)
                throw new InvalidCastException("HelperType must be derived from A");
            _helperType = value;
        }
    }
}

Ich habe das Gefühl, dass ich vielleicht ein bisschen naiv bin, daher wäre jede Rückmeldung willkommen.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X