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 .
T
Devralma / 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 U
aslında çevirir typeof(T).IsAssignableFrom(typeof(U))
.
T
sı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)
T
typeof(SomeInterface).IsAssignableFrom(typeof(T))
TOther
SomeInterface
SomeInterface
IsAssignableFrom
, TypeInfo
TypeInfo 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:
true
eğerc
mevcut veType
aynı tipini temsil veya geçerli eğerType
miras hiyerarşide bulunanc
veya geçerli eğerType
birinterface
oc
uygular veya eğerc
bir genel tür parametre ve geçerliType
kısıtlamalarından birini temsilc
veyac
bir değer türünü temsil ediyorsa ve geçerli ( Visual Basic'te)Type
temsil ediyorsa . Bu koşulların hiçbiri varsa , ya eğer olduğunu .Nullable<c>
Nullable(Of c)
false
true
c
null
Daha Employee IsAssignableFrom T
sonra T
miras 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,Employee
miras 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 T
devralır veya uygular bazı class
/ interface
kullanı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 DerivedType
bir ö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 HorizontalRun
ve 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.
SomeClass
Doğrudan türetilmediği sürece bu işe yarar BaseClass
.
Bir nesnenin o
bir sınıfı miras aldığını veya bir arabirim uygulayıp uygulamadığını anlamanın alternatif yolları , is
ve as
iş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, is
operatö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, as
operatö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 T
türe sahipseniz, @ nikeee'nin cevabını kullanın.