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
}
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
}
Yanıtlar:
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).GetTypeInfo())
T inherits Uaslında çevirir typeof(T).IsAssignableFrom(typeof(U)).
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
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())
Sınıfta kısıtlamalar kullanabilirsiniz.
MyClass<T> where T : Employee
Http://msdn.microsoft.com/en-us/library/d5x73970.aspx adresine bir göz atın.
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.
Doğru sözdizimi
typeof(Employee).IsAssignableFrom(typeof(T))
Dönüş Değeri:
trueeğercmevcut veTypeaynı tipini temsil veya geçerli eğerTypemiras hiyerarşide bulunancveya geçerli eğerTypebirinterfaceocuygular veya eğercbir genel tür parametre ve geçerliTypekısıtlamalarından birini temsilcveyacbir 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
Daha Employee IsAssignableFrom Tsonra Tmiras alır Employee.
Kullanım
typeof(T).IsAssignableFrom(typeof(Employee))
true sadece ikisinden biri olduğunda geri döner
T ve Employee aynı türü temsil eder; veya,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))
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;
}
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
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.
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.