it-swarm.com.de

Wie überprüfe ich, ob ein Typ ein Subtyp ist OR der Typ eines Objekts?

So überprüfen Sie, ob ein Typ eine Unterklasse eines anderen Typs in C # ist:

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

Dies wird jedoch fehlschlagen:

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

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

312
Daniel T.

Anscheinend nein.

Hier sind die Optionen:

Type.IsSubclassOf

Wie Sie bereits herausgefunden haben, funktioniert dies nicht, wenn die beiden Typen identisch sind. Hier ist ein Beispiel LINQPad Programm, das Folgendes 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

Was darauf hinweist, dass Derived eine Unterklasse von Base ist, aber dass Base (offensichtlich) keine Unterklasse von sich selbst ist.

Type.IsAssignableFrom

Nun wird dies Ihre spezielle Frage beantworten, aber es wird Ihnen auch falsche Positive geben. Eric Lippert hat in den Kommentaren darauf hingewiesen, dass die Methode zwar True für die beiden obigen Fragen zurückgibt, jedoch auch True für diese Fragen, die Sie wahrscheinlich nicht möchten:

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 folgende Ausgabe:

True
True
True

Das letzte True dort würde anzeigen, wenn die Methode nur die gestellte Frage beantwortete, dass uint[] erbt von int[] oder dass es sich um denselben Typ handelt, was eindeutig nicht der Fall ist.

Also ist IsAssignableFrom auch nicht ganz richtig.

is und as

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

Mit anderen Worten, dies wird nicht kompiliert:

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

noch wird dies:

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

noch wird dies:

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

Fazit

Obwohl die oben genannten Methoden Ihren Anforderungen entsprechen, ist die einzige richtige Antwort auf Ihre Frage (wie ich sie sehe), dass Sie eine zusätzliche Prüfung benötigen:

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

was in einer methode natürlich sinnvoller ist:

public bool IsSameOrSubclass(Type potentialBase, Type potentialDescendant)
{
    return potentialDescendant.IsSubclassOf(potentialBase)
           || potentialDescendant == potentialBase;
}
typeof(BaseClass).IsAssignableFrom(unknownType);
30
Marc Gravell

Verwenden Sie stattdessen Type.IsAssignableFrom .

9
Thomas

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

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

weil IsAssignableFrom nach einem TypeInfo Objekt fragt. Sie können die GetTypeInfo() -Methode von System.Reflection Verwenden:

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

1
BrunoSerrano

Ich poste diese Antwort mit der Hoffnung, dass jemand mit mir teilt, ob und warum es eine schlechte Idee wäre. In meiner Anwendung habe ich eine Eigenschaft vom Typ, die ich überprüfen möchte, um sicherzustellen, dass es sich um Typ (A) oder Typ (B) handelt, wobei B eine von A abgeleitete Klasse ist. Also mein Code:

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 fühle mich hier vielleicht ein bisschen naiv, also wäre jedes Feedback willkommen.

0
baskren