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 T
mewarisi / 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 U
sebenarnya diterjemahkan menjadi typeof(T).IsAssignableFrom(typeof(U))
.
T
dibatasi ke beberapa jenis lain TOther
, kemudian ketika dijalankan, typeof(T)
akan benar-benar mengevaluasi ke typeof(TOther)
dan bukan jenis apa pun yang T
sebenarnya Anda lewati, dan dalam kasus itu, typeof(SomeInterface).IsAssignableFrom(typeof(T))
akan gagal (dengan asumsi TOther
tidak juga diterapkan SomeInterface
), meskipun jenis beton Anda benar-benar diterapkan SomeInterface
.
IsAssignableFrom
dari TypeInfo
kelas 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:
true
jikac
dan arusType
mewakili tipe yang sama, atau jika arusType
berada dalam hierarki pewarisanc
, atau jika arusType
adalahinterface
yangc
mengimplementasikan, atau jikac
adalah tipe parameter generik dan arusType
mewakili salah satu batasanc
, atau jikac
mewakili tipe nilai dan arusType
mewakiliNullable<c>
(Nullable(Of c)
dalam Visual Basic).false
jika tidak ada dari kondisi initrue
, atau jikac
adanull
.
Jika Employee IsAssignableFrom T
kemudian T
mewarisi dari Employee
.
Penggunaan
typeof(T).IsAssignableFrom(typeof(Employee))
kembali true
hanya jika salah satunya
T
dan Employee
mewakili tipe yang sama; atau,Employee
mewarisi dari T
.Ini mungkin penggunaan yang dimaksudkan dalam beberapa kasus, tetapi untuk pertanyaan asli (dan penggunaan yang lebih umum), untuk menentukan kapan T
mewarisi 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 DerivedType
ke 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 HorizontalRun
dan 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.
SomeClass
tidak secara langsung berasal dari BaseClass
.
Cara alternatif untuk mengetahui apakah suatu objek o
mewarisi kelas atau mengimplementasikan antarmuka adalah dengan menggunakan is
danas
operator .
Jika Anda hanya ingin mengetahui apakah suatu objek mewarisi kelas atau mengimplementasikan antarmuka, is
operator 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, as
operator 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.