Có cách nào để kiểm tra xem T có kế thừa / triển khai một lớp / giao diện không?
private void MyGenericClass<T> ()
{
if(T ... inherits or implements some class/interface
}
Có cách nào để kiểm tra xem T có kế thừa / triển khai một lớp / giao diện không?
private void MyGenericClass<T> ()
{
if(T ... inherits or implements some class/interface
}
Câu trả lời:
Có một Phương thức được gọi là Type.IsAssignableFrom () .
Để kiểm tra xem T
kế thừa / hiện thực Employee
:
typeof(Employee).IsAssignableFrom(typeof(T));
Nếu bạn đang nhắm mục tiêu .NET Core, phương pháp đã chuyển sang TypeInfo:
typeof(Employee).GetTypeInfo().IsAssignableFrom(typeof(T).GetTypeInfo())
T inherits U
thực sự dịch sang typeof(T).IsAssignableFrom(typeof(U))
.
T
là nếu bị hạn chế đối với một số kiểu khác TOther
, thì khi được thực thi, typeof(T)
sẽ thực sự đánh giá typeof(TOther)
và không phải bất kỳ kiểu T
nào bạn đã thực sự vượt qua và trong trường hợp đó, typeof(SomeInterface).IsAssignableFrom(typeof(T))
sẽ không thành công (giả sử TOther
cũng không triển khai SomeInterface
), mặc dù loại bê tông của bạn đã thực hiện SomeInterface
.
IsAssignableFrom
của TypeInfo
lớp chỉ chấp nhận TypeInfo vì nó là đối số duy nhất, vì vậy mẫu phải như sau:typeof(Employee).GetTypeInfo().IsAssignableFrom(typeof(T).GetTypeInfo())
Bạn có thể sử dụng các ràng buộc trên lớp.
MyClass<T> where T : Employee
Hãy xem tại http://msdn.microsoft.com/en-us/library/d5x73970.aspx
Nếu bạn muốn kiểm tra trong quá trình biên dịch: Lỗi nếu T
KHÔNG triển khai giao diện / lớp mong muốn, bạn có thể sử dụng ràng buộc sau
public void MyRestrictedMethod<T>() where T : MyInterface1, MyInterface2, MySuperClass
{
//Code of my method here, clean without any check for type constraints.
}
Tôi hy vọng rằng sẽ giúp.
Cú pháp đúng là
typeof(Employee).IsAssignableFrom(typeof(T))
Return Value:
true
nếuc
và hiệnType
đại diện cho cùng loại, hoặc nếu hiện tạiType
là trong hệ thống phân cấp thừa kếc
, hoặc nếu hiện tạiType
là mộtinterface
màc
dụng cụ, hoặc nếuc
là một tham số kiểu chung chung và hiệnType
đại diện cho một trong những hạn chế củac
, hoặc nếuc
đại diện cho một kiểu giá trị vàType
đại diện hiện tạiNullable<c>
(Nullable(Of c)
trong Visual Basic).false
nếu không có điều kiện nào trong số nàytrue
, hoặc nếuc
cónull
.
Nếu Employee IsAssignableFrom T
thì T
kế thừa từ Employee
.
Việc sử dụng
typeof(T).IsAssignableFrom(typeof(Employee))
true
chỉ trả lại khi một trong hai
T
và Employee
đại diện cho cùng một loại; hoặc là,Employee
kế thừa từ T
.Đây có thể là mục đích sử dụng trong một số trường hợp, nhưng đối với câu hỏi ban đầu (và cách sử dụng phổ biến hơn), để xác định khi nào T
kế thừa hoặc triển khai một số class
/ interface
, hãy sử dụng:
typeof(Employee).IsAssignableFrom(typeof(T))
Những gì mọi người thực sự có nghĩa là:
typeof(BaseType).IsAssignableFrom(typeof(DerivedType)) // => true
bởi vì bạn có thể chỉ định theo nghĩa đen từ một phiên bản của a DerivedType
thành một phiên bản của BaseType
:
DerivedType childInstance = new DerivedType();
BaseType parentInstance = childInstance; // okay, assigning base from derived
childInstance = (DerivedType) parentInstance; // not okay, assigning derived from base
khi nào
public class BaseType {}
public class DerivedType : BaseType {}
Và một số ví dụ cụ thể nếu bạn gặp khó khăn trong việc quấn lấy nó:
(thông qua LinqPad, do đó HorizontalRun
và 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
Thật
child1-> baseclass
Sai
baseclass-> child1
Thật
child2-> baseclass
Sai
baseclass-> child2
Thật
nobase-> baseclass
Sai
baseclass-> nobase
Sai
và
- THẤT BẠI: c1 = b1
- b1 = c1
- THẤT BẠI: c2 = b1
- b1 = c2
Mặc dù IsAssignableFrom là cách tốt nhất như những người khác đã nêu, nhưng nếu bạn chỉ cần kiểm tra xem một lớp có kế thừa từ lớp khác hay typeof(T).BaseType == typeof(SomeClass)
không , thì công việc cũng vậy.
SomeClass
không có nguồn gốc trực tiếp từ BaseClass
.
Các cách thay thế để biết một đối tượng o
kế thừa một lớp hoặc triển khai một giao diện là sử dụng toán tử is
and as
.
Nếu bạn chỉ muốn biết liệu một đối tượng có kế thừa một lớp hay triển khai một giao diện hay không, is
toán tử sẽ trả về một kết quả boolean:
bool isCompatibleType = (o is BaseType || o is IInterface);
Nếu bạn muốn sử dụng lớp kế thừa hoặc giao diện được triển khai sau khi kiểm tra của mình, as
nhà điều hành sẽ thực hiện truyền an toàn, trả về một tham chiếu đến lớp kế thừa hoặc giao diện được triển khai nếu tương thích hoặc null nếu không tương thích:
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.
Nếu bạn chỉ có loại T
, thì hãy sử dụng câu trả lời của @ nikeee.