web-dev-qa-db-fra.com

Vérifiez si 'T' hérite ou implémente une classe / interface

Existe-t-il un moyen de tester si T hérite/implémente une classe/interface?

private void MyGenericClass<T> ()
{
    if(T ... inherits or implements some class/interface
}
82
user1229895

Il existe une méthode appelée Type.IsAssignableFrom () .

Pour vérifier si T hérite/implémente Employee:

typeof(Employee).IsAssignableFrom(typeof(T));

Si vous ciblez .NET Core, la méthode est passée à TypeInfo:

typeof(Employee).GetTypeInfo().IsAssignableFrom(typeof(T).Ge‌​tTypeInfo())
115
nikeee

Vous pouvez utiliser des contraintes sur la classe.

MyClass<T> where T : Employee

Jetez un œil à http://msdn.Microsoft.com/en-us/library/d5x73970.aspx

29
Sachin Kainth

Si vous souhaitez vérifier pendant la compilation: Erreur si si Tne PAS implémente l'interface/classe souhaitée, vous pouvez utiliser la contrainte suivante

public void MyRestrictedMethod<T>() where T : MyInterface1, MyInterface2, MySuperClass
{
    //Code of my method here, clean without any check for type constraints.
}

J'espère que ça aide.

12
snajahi

La syntaxe correcte est

typeof(Employee).IsAssignableFrom(typeof(T))

Documentation

Valeur de retour: true si c et l'actuel Type représentent le même type, ou si Type actuel est dans la hiérarchie d'héritage de c, ou si le Type actuel est un interface que c implémente, ou si c est un paramètre de type générique et le courant Type représente l'une des contraintes de c, ou si c représente un type de valeur et le courant Type représente Nullable<c> (Nullable(Of c) en Visual Basic). false si aucune de ces conditions n'est true, ou si c est null.

source

Explication

Si Employee IsAssignableFrom T Alors T hérite de Employee.

L'usage

typeof(T).IsAssignableFrom(typeof(Employee)) 

renvoie true uniquement lorsque l'un ou l'autre

  1. T et Employee représentent le même type; ou,
  2. Employee hérite de T.

Cela peut être une utilisation prévue dans certains cas, mais pour la question d'origine (et l'utilisation la plus courante), pour déterminer quand T hérite ou implémente certains class/interface, utilisez:

typeof(Employee).IsAssignableFrom(typeof(T))
11
Luke M Willis

Ce que tout le monde veut vraiment dire, c'est:

typeof(BaseType).IsAssignableFrom(typeof(DerivedType)) // => true

car vous pouvez littéralement assigner de une instance d'un DerivedType à une instance d'un BaseType:

DerivedType childInstance = new DerivedType();
BaseType parentInstance = childInstance; // okay, assigning base from derived
childInstance = (DerivedType) parentInstance; // not okay, assigning derived from base

quand

public class BaseType {}
public class DerivedType : BaseType {}

Et quelques exemples concrets si vous avez du mal à envelopper votre tête:

(via LinqPad, d'où les HorizontalRun et Dump)

void Main()
{
    // http://stackoverflow.com/questions/10718364/check-if-t-inherits-or-implements-a-class-interface

    var b1 = new BaseClass1();

    var c1 = new ChildClass1();
    var c2 = new ChildClass2();
    var nb = new nobase();

    Util.HorizontalRun(
        "baseclass->baseclass,child1->baseclass,baseclass->child1,child2->baseclass,baseclass->child2,nobase->baseclass,baseclass->nobase",
        b1.IsAssignableFrom(typeof(BaseClass1)),
        c1.IsAssignableFrom(typeof(BaseClass1)),
        b1.IsAssignableFrom(typeof(ChildClass1)),
        c2.IsAssignableFrom(typeof(BaseClass1)),
        b1.IsAssignableFrom(typeof(ChildClass2)),
        nb.IsAssignableFrom(typeof(BaseClass1)),
        b1.IsAssignableFrom(typeof(nobase))
        ).Dump("Results");

    var results = new List<string>();
    string test;

    test = "c1 = b1";
    try {
        c1 = (ChildClass1) b1;
        results.Add(test);
    } catch { results.Add("FAIL: " + test); }

    test = "b1 = c1";
    try {
        b1 = c1;
        results.Add(test);
    } catch { results.Add("FAIL: " + test); }

    test = "c2 = b1";
    try {
        c2 = (ChildClass2) b1;
        results.Add(test);
    } catch { results.Add("FAIL: " + test); }

    test = "b1 = c2";
    try {
        b1 = c2;
        results.Add(test);
    } catch { results.Add("FAIL: " + test); }

    results.Dump();
}

// Define other methods and classes here
public static class exts {
    public static bool IsAssignableFrom<T>(this T entity, Type baseType) {
        return typeof(T).IsAssignableFrom(baseType);
    }
}


class BaseClass1 {
    public int id;
}

class ChildClass1 : BaseClass1 {
    public string name;
}

class ChildClass2 : ChildClass1 {
    public string descr;
}

class nobase {
    public int id;
    public string name;
    public string descr;
}

Résultats

classe de base-> classe de base

Vrai

enfant1-> classe de base

False

classe de base-> enfant1

Vrai

child2-> baseclass

False

classe de base-> enfant2

Vrai

nobase-> baseclass

False

classe de base-> nobase

False

et

  • ÉCHEC: c1 = b1
  • b1 = c1
  • ÉCHEC: c2 = b1
  • b1 = c2
8
drzaus

Je crois que la syntaxe est: typeof(Employee).IsAssignableFrom(typeof(T));

2
Chalky

D'autres façons de savoir si un objet o hérite d'une classe ou implémente une interface consiste à utiliser les opérateurs is et as.

Si vous voulez seulement savoir si un objet hérite d'une classe ou implémente une interface, l'opérateur is renverra un résultat booléen:

bool isCompatibleType = (o is BaseType || o is IInterface);

Si vous souhaitez utiliser la classe héritée ou l'interface implémentée après votre test, l'opérateur as effectuera une conversion sécurisée, renvoyant une référence à la classe héritée ou à l'interface implémentée si compatible ou null si non compatible:

BaseType b = o as BaseType; // Null if d does not inherit from BaseType.

IInterface i = o as IInterface; // Null if d does not implement IInterface.

Si vous n'avez que le type T, utilisez la réponse de @ nikeee.

0
Suncat2000

Bien que IsAssignableFrom soit la meilleure façon, comme d'autres l'ont dit, si vous avez seulement besoin de vérifier si une classe hérite d'une autre, typeof(T).BaseType == typeof(SomeClass) fait aussi le travail.

0
Jed