Type t = typeof(obj1);
if (t == typeof(int))
// Some code here
Đây là một lỗi. Toán tử typeof trong C # chỉ có thể lấy tên kiểu, không phải đối tượng.
if (obj1.GetType() == typeof(int))
// Some code here
Điều này sẽ làm việc, nhưng có thể không như bạn mong đợi. Đối với các loại giá trị, như bạn đã trình bày ở đây, có thể chấp nhận được, nhưng đối với các loại tham chiếu, nó sẽ chỉ trả về đúng nếu loại đó là cùng loại, không phải là thứ khác trong hệ thống phân cấp thừa kế. Ví dụ:
class Animal{}
class Dog : Animal{}
static void Foo(){
object o = new Dog();
if(o.GetType() == typeof(Animal))
Console.WriteLine("o is an animal");
Console.WriteLine("o is something else");
}
Điều này sẽ in "o is something else", bởi vì loại olà Dog, không Animal. Bạn có thể làm cho công việc này, tuy nhiên, nếu bạn sử dụng IsAssignableFromphương thức của Typelớp.
if(typeof(Animal).IsAssignableFrom(o.GetType())) // note use of tested type
Console.WriteLine("o is an animal");
Kỹ thuật này vẫn để lại một vấn đề lớn, mặc dù. Nếu biến của bạn là null, lệnh gọi GetType()sẽ ném NullReferenceException. Vì vậy, để làm cho nó hoạt động chính xác, bạn sẽ làm:
if(o != null && typeof(Animal).IsAssignableFrom(o.GetType()))
Console.WriteLine("o is an animal");
Với điều này, bạn có hành vi tương đương của istừ khóa. Do đó, nếu đây là hành vi bạn muốn, bạn nên sử dụng istừ khóa, dễ đọc hơn và hiệu quả hơn.
if(o is Animal)
Console.WriteLine("o is an animal");
Tuy nhiên, trong hầu hết các trường hợp, istừ khóa vẫn không phải là thứ bạn thực sự muốn, bởi vì thường thì không đủ để biết rằng một đối tượng thuộc một loại nhất định. Thông thường, bạn muốn thực sự sử dụng đối tượng đó như là một thể hiện của loại đó, cũng yêu cầu truyền nó. Và vì vậy bạn có thể thấy mình viết mã như thế này:
if(o is Animal)
((Animal)o).Speak();
Nhưng điều đó làm cho CLR kiểm tra loại đối tượng lên đến hai lần. Nó sẽ kiểm tra nó một lần để thỏa mãn người isvận hành, và nếu othực sự là một Animal, chúng tôi làm cho nó kiểm tra lại để xác thực diễn viên.
Thay vào đó, hiệu quả hơn là làm điều này:
Animal a = o as Animal;
if(a != null)
a.Speak();
Nhà asđiều hành là một diễn viên sẽ không ném ngoại lệ nếu thất bại, thay vào đó trở lại null. Bằng cách này, CLR kiểm tra loại đối tượng chỉ một lần và sau đó, chúng ta chỉ cần thực hiện kiểm tra null, hiệu quả hơn.
Nhưng hãy cẩn thận: nhiều người rơi vào một cái bẫy với as. Bởi vì nó không đưa ra ngoại lệ, một số người nghĩ rằng đó là dàn diễn viên "an toàn" và họ sử dụng nó một cách độc quyền, làm cho các diễn viên thông thường lẩn tránh. Điều này dẫn đến các lỗi như thế này:
(o as Animal).Speak();
Trong trường hợp này, nhà phát triển rõ ràng giả định rằng osẽ luôn luôn là một Animal, và miễn là giả định của họ là chính xác, mọi thứ đều hoạt động tốt. Nhưng nếu họ sai, thì cái họ kết thúc ở đây là a NullReferenceException. Với một dàn diễn viên thông thường, họ sẽ có được một InvalidCastExceptionthay thế, điều này sẽ xác định chính xác hơn vấn đề.
Đôi khi, lỗi này có thể khó tìm:
class Foo{
readonly Animal animal;
public Foo(object o){
animal = o as Animal;
}
public void Interact(){
animal.Speak();
}
}
Đây là một trường hợp các nhà phát triển được rõ ràng mong đợi olà một Animalmọi thời gian, nhưng điều này là không rõ ràng trong các nhà xây dựng, nơi mà các asdiễn viên được sử dụng. Không rõ ràng cho đến khi bạn có được Interactphương pháp, nơi mà animaltrường được dự kiến sẽ được gán tích cực. Trong trường hợp này, không chỉ bạn kết thúc với một ngoại lệ sai lệch, mà nó còn không được ném cho đến khi có khả năng muộn hơn nhiều so với khi xảy ra lỗi thực tế.
Tóm tắt:
Nếu bạn chỉ cần biết liệu một đối tượng có thuộc loại nào đó hay không, hãy sử dụng is.
Nếu bạn cần coi một đối tượng là một thể hiện của một loại nhất định, nhưng bạn không biết chắc chắn rằng đối tượng đó sẽ thuộc loại đó, hãy sử dụng asvà kiểm tra null.
Nếu bạn cần coi một đối tượng là một thể hiện của một loại nhất định và đối tượng được cho là thuộc loại đó, hãy sử dụng một biểu mẫu thông thường.
as!