'T'nin bir sınıfı / arayüzü miras alıp almadığını kontrol edin


94

T'nin bir sınıfı / arabirimi miras alıp almadığını test etmenin bir yolu var mı?

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

4
bu işe yarıyor gibi görünüyor ... if (typeof (TestClass) .IsAssignableFrom (typeof (T))), birisi şüphelerimi doğrulayabilir mi? Teşekkürler!
user1229895

Bu cevabın birçok kez tekrarlandığından kesinlikle eminim!
Felix K.

3
Felix K Bu cevap birçok kez yinelenmiş olsa bile, birçok erkeğe birçok kez yardımcı oluyor;) ... beş dakika önce benim gibi :)
Samuel

Yanıtlar:


139

Type.IsAssignableFrom () adında bir Yöntem vardır .

TDevralma / uygulama olup olmadığını kontrol etmek için Employee:

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

.NET Core'u hedefliyorsanız, yöntem TypeInfo'ya taşındı:

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

cevabınızı bir örnekle güncellemelisiniz, örn. typeof (T) .IsAssignableFrom (typeof (IMyInterface))
Dr. Andrew Burnett-Thompson

Nikeee yapılmadı; eski cevap hala oradadır. :) Sorunun ne olduğunu anlamak için birkaç saniye ayırdım. Neyse, +1, .net çerçevesinin güzel bir özelliği.
Samuel

Aslında, bahsetme şeklin bir süre önce sahip olduğum yol. Bunu düzelttim. Önceki yorumlara bakın. T inherits Uaslında çevirir typeof(T).IsAssignableFrom(typeof(U)).
nikeee

3
Bu neredeyse işe yarasa da, başka bir türle Tsınırlandırılırsa TOther, o zaman yürütüldüğünde, gerçekten geçtiğiniz türden değil typeof(T), gerçekten değerlendireceği ve bu durumda başarısız olacağı bir sorun vardır ( aynı zamanda uygulanmazsa ), Somut türünüz uygulansa bile . typeof(TOther)Ttypeof(SomeInterface).IsAssignableFrom(typeof(T))TOtherSomeInterfaceSomeInterface
Dave Cousineau

1
.Net sınıfının çekirdeğinde IsAssignableFrom, TypeInfoTypeInfo yalnızca argüman olarak kabul edilir, bu nedenle örnek aşağıdaki gibi olmalıdır:typeof(Employee).GetTypeInfo().IsAssignableFrom(typeof(T).GetTypeInfo())
Ka


16

Eğer derleme sırasında kontrol etmek istiyorsanız: Hata varsa eğer T DEĞİLDİR istenen arayüz / sınıf uygulamak, aşağıdaki kısıtlamayı kullanabilirsiniz

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

Umarım bu yardımcı olur.


13

Doğru sözdizimi

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

Dokümantasyon

Dönüş Değeri: true eğer cmevcut ve Typeaynı tipini temsil veya geçerli eğer Typemiras hiyerarşide bulunan cveya geçerli eğer Typebir interfaceo cuygular veya eğer cbir genel tür parametre ve geçerli Typekısıtlamalarından birini temsil cveya cbir değer türünü temsil ediyorsa ve geçerli ( Visual Basic'te) Typetemsil ediyorsa . Bu koşulların hiçbiri varsa , ya eğer olduğunu .Nullable<c>Nullable(Of c)falsetruecnull

kaynak

Açıklama

Daha Employee IsAssignableFrom Tsonra Tmiras alır Employee.

Kullanım

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

true sadece ikisinden biri olduğunda geri döner

  1. T ve Employee aynı türü temsil eder; veya,
  2. Employeemiras alır T.

Bu içinde kullanım amacına olabilir bazı durumlarda, ancak asıl soruya (ve daha yaygın kullanım) için, belirleme sırasında Tdevralır veya uygular bazı class/ interfacekullanın:

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

9

Herkesin gerçekte anlamı şudur:

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

kelimenin tam anlamıyla çünkü gelen atamak bir örneğine DerivedTypebir örneğine BaseType:

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

ne zaman

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

Ve kafanızı etrafına dolamakta sorun yaşıyorsanız bazı somut örnekler:

(LinqPad aracılığıyla, dolayısıyla HorizontalRunve 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;
}

Sonuçlar

baseclass-> baseclass

Doğru

child1-> baseclass

Yanlış

baseclass-> child1

Doğru

child2-> temel sınıf

Yanlış

baseclass-> child2

Doğru

nobase-> baseclass

Yanlış

baseclass-> nobase

Yanlış

ve

  • BAŞARISIZ: c1 = b1
  • b1 = c1
  • BAŞARISIZ: c2 = b1
  • b1 = c2

2

Söz diziminin şu olduğuna inanıyorum: typeof(Employee).IsAssignableFrom(typeof(T));


Bu, amaçlanan sözdizimidir. +1
Luke

0

IsAssignableFrom, diğerlerinin de belirttiği gibi en iyi yol olsa da, yalnızca bir sınıfın diğerinden miras alıp almadığını kontrol etmeniz gerekiyorsa typeof(T).BaseType == typeof(SomeClass), işi de yapar.


SomeClassDoğrudan türetilmediği sürece bu işe yarar BaseClass.
Suncat2000

0

Bir nesnenin obir sınıfı miras aldığını veya bir arabirim uygulayıp uygulamadığını anlamanın alternatif yolları , isve asişleçlerini kullanmaktır .

Yalnızca bir nesnenin bir sınıfı miras alıp almadığını veya bir arabirim uygulayıp uygulamadığını bilmek istiyorsanız, isoperatör bir boole sonucu döndürür:

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

Testinizden sonra devralınan sınıfı veya uygulanan arayüzü kullanmak istiyorsanız, asoperatör güvenli bir dönüşüm gerçekleştirecek ve uyumluysa veya uyumlu değilse boşsa miras alınan sınıfa veya uygulanan arayüze bir referans döndürecektir:

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.

Yalnızca Ttüre sahipseniz, @ nikeee'nin cevabını kullanın.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.