Apakah ada cara untuk menguji apakah T mewarisi / mengimplementasikan kelas / antarmuka?
private void MyGenericClass<T> ()
{
if(T ... inherits or implements some class/interface
}
Apakah ada cara untuk menguji apakah T mewarisi / mengimplementasikan kelas / antarmuka?
private void MyGenericClass<T> ()
{
if(T ... inherits or implements some class/interface
}
Jawaban:
Ada Metode yang disebut Type.IsAssignableFrom () .
Untuk memeriksa apakah Tmewarisi / mengimplementasikan Employee:
typeof(Employee).IsAssignableFrom(typeof(T));
Jika Anda menargetkan .NET Core, metode telah dipindahkan ke TypeInfo:
typeof(Employee).GetTypeInfo().IsAssignableFrom(typeof(T).GetTypeInfo())
T inherits Usebenarnya diterjemahkan menjadi typeof(T).IsAssignableFrom(typeof(U)).
Tdibatasi ke beberapa jenis lain TOther, kemudian ketika dijalankan, typeof(T)akan benar-benar mengevaluasi ke typeof(TOther)dan bukan jenis apa pun yang Tsebenarnya Anda lewati, dan dalam kasus itu, typeof(SomeInterface).IsAssignableFrom(typeof(T))akan gagal (dengan asumsi TOthertidak juga diterapkan SomeInterface), meskipun jenis beton Anda benar-benar diterapkan SomeInterface.
IsAssignableFromdari TypeInfokelas hanya menerima TypeInfo karena hanya argumen itu, sehingga sampel harus berikut:typeof(Employee).GetTypeInfo().IsAssignableFrom(typeof(T).GetTypeInfo())
Anda dapat menggunakan batasan di kelas.
MyClass<T> where T : Employee
Jika Anda ingin memeriksa selama kompilasi: Kesalahan jika T TIDAK menerapkan antarmuka / kelas yang diinginkan, Anda dapat menggunakan batasan berikut
public void MyRestrictedMethod<T>() where T : MyInterface1, MyInterface2, MySuperClass
{
//Code of my method here, clean without any check for type constraints.
}
Saya harap itu membantu.
Sintaks yang benar adalah
typeof(Employee).IsAssignableFrom(typeof(T))
Return Value:
truejikacdan arusTypemewakili tipe yang sama, atau jika arusTypeberada dalam hierarki pewarisanc, atau jika arusTypeadalahinterfaceyangcmengimplementasikan, atau jikacadalah tipe parameter generik dan arusTypemewakili salah satu batasanc, atau jikacmewakili tipe nilai dan arusTypemewakiliNullable<c>(Nullable(Of c)dalam Visual Basic).falsejika tidak ada dari kondisi initrue, atau jikacadanull.
Jika Employee IsAssignableFrom Tkemudian Tmewarisi dari Employee.
Penggunaan
typeof(T).IsAssignableFrom(typeof(Employee))
kembali true hanya jika salah satunya
Tdan Employeemewakili tipe yang sama; atau,Employeemewarisi dari T.Ini mungkin penggunaan yang dimaksudkan dalam beberapa kasus, tetapi untuk pertanyaan asli (dan penggunaan yang lebih umum), untuk menentukan kapan Tmewarisi atau mengimplementasikan beberapa class/ interface, gunakan:
typeof(Employee).IsAssignableFrom(typeof(T))
Yang dimaksud setiap orang adalah:
typeof(BaseType).IsAssignableFrom(typeof(DerivedType)) // => true
karena Anda benar-benar dapat menetapkan dari sebuah contoh DerivedTypeke sebuah contoh dari BaseType:
DerivedType childInstance = new DerivedType();
BaseType parentInstance = childInstance; // okay, assigning base from derived
childInstance = (DerivedType) parentInstance; // not okay, assigning derived from base
kapan
public class BaseType {}
public class DerivedType : BaseType {}
Dan beberapa contoh konkret jika Anda kesulitan membungkus kepala Anda di sekitarnya:
(melalui LinqPad, karenanya HorizontalRundan 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
Benar
child1-> baseclass
Salah
baseclass-> child1
Benar
child2-> baseclass
Salah
baseclass-> child2
Benar
nobase-> baseclass
Salah
baseclass-> nobase
Salah
dan
- GAGAL: c1 = b1
- b1 = c1
- GAGAL: c2 = b1
- b1 = c2
Meskipun IsAssignableFrom adalah cara terbaik seperti yang dinyatakan orang lain, jika Anda hanya perlu memeriksa apakah kelas mewarisi dari kelas lain, typeof(T).BaseType == typeof(SomeClass)lakukan pekerjaan itu juga.
SomeClasstidak secara langsung berasal dari BaseClass.
Cara alternatif untuk mengetahui apakah suatu objek omewarisi kelas atau mengimplementasikan antarmuka adalah dengan menggunakan isdanas operator .
Jika Anda hanya ingin mengetahui apakah suatu objek mewarisi kelas atau mengimplementasikan antarmuka, isoperator akan mengembalikan hasil boolean:
bool isCompatibleType = (o is BaseType || o is IInterface);
Jika Anda ingin menggunakan kelas yang diwariskan atau antarmuka yang diimplementasikan setelah pengujian Anda, asoperator akan melakukan transmisi yang aman, mengembalikan referensi ke kelas yang diwariskan atau antarmuka yang diimplementasikan jika kompatibel atau null jika tidak kompatibel:
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.
Jika Anda hanya memiliki tipe T, gunakan jawaban @ nikeee.