类型检查:typeof、GetType 还是 is?
技术背景
在 C# 编程中,类型检查是一项常见的操作,用于确定对象的类型。typeof
、GetType
和 is
是三种不同的类型检查方式,它们在不同的场景下发挥着作用。了解它们的区别和适用场景,能够帮助开发者更高效地进行类型检查和编程。
实现步骤
1. typeof
操作符
typeof
操作符用于在编译时获取类型信息,它接受一个类型名称作为参数。例如:
2. GetType
方法
GetType
方法是一个实例方法,用于在运行时获取对象的实际类型。例如:
1 2
| int num = 10; Type t = num.GetType();
|
3. is
关键字
is
关键字用于检查对象是否是指定类型或其派生类型的实例,返回一个布尔值。例如:
1 2 3 4 5
| class Animal { } class Dog : Animal { }
Dog spot = new Dog(); bool result = spot is Animal;
|
4. typeof(T)
的使用
typeof(T)
在泛型方法中使用,T
的类型在编译时确定。例如:
1 2 3 4 5 6 7
| string Foo<T>(T parameter) { return typeof(T).Name; }
Animal probably_a_dog = new Dog(); Dog definitely_a_dog = new Dog();
string result1 = Foo(probably_a_dog); string result2 = Foo(definitely_a_dog);
|
5. as
操作符
as
操作符用于尝试将对象转换为指定类型,如果转换失败则返回 null
。例如:
1 2 3 4 5
| Foo foo = obj as Foo; if (foo != null) { }
|
6. C# 7+ 的模式匹配
在 C# 7+ 中,可以使用模式匹配简化类型检查和转换。例如:
1 2 3 4
| if (obj1 is int integerValue) { integerValue++; }
|
7. Type
类的方法
还可以使用 Type
类的 IsInstanceOfType
、IsAssignableFrom
和 IsSubClassOf
方法进行类型检查。例如:
1 2 3 4 5 6 7 8 9
| public class Animal { } public interface ITrainable { } public class Dog : Animal, ITrainable { }
Animal dog = new Dog();
bool result1 = typeof(Animal).IsInstanceOfType(dog); bool result2 = typeof(Animal).IsAssignableFrom(dog.GetType()); bool result3 = dog.GetType().IsSubclassOf(typeof(Animal));
|
核心代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
| class Animal { } class Dog : Animal { }
void PrintTypes(Animal a) { Console.WriteLine(a.GetType() == typeof(Animal)); Console.WriteLine(a is Animal); Console.WriteLine(a.GetType() == typeof(Dog)); Console.WriteLine(a is Dog); }
Dog spot = new Dog(); PrintTypes(spot);
string Foo<T>(T parameter) { return typeof(T).Name; }
Animal probably_a_dog = new Dog(); Dog definitely_a_dog = new Dog();
Console.WriteLine(Foo(probably_a_dog)); Console.WriteLine(Foo(definitely_a_dog));
object obj = new Foo(); Foo foo = obj as Foo; if (foo != null) { }
object obj1 = 10; if (obj1 is int integerValue) { integerValue++; }
public class Animal { } public interface ITrainable { } public class Dog : Animal, ITrainable { }
Animal dog = new Dog();
Console.WriteLine(typeof(Animal).IsInstanceOfType(dog)); Console.WriteLine(typeof(Animal).IsAssignableFrom(dog.GetType())); Console.WriteLine(dog.GetType().IsSubclassOf(typeof(Animal)));
|
最佳实践
- 仅需判断对象是否为某类型时:使用
is
关键字,它简洁且能处理继承关系。 - 需要将对象作为特定类型处理,但不确定对象类型时:使用
as
操作符并检查 null
,这样可以避免多次类型检查。 - 需要在编译时获取类型信息时:使用
typeof
操作符。 - 需要在运行时获取对象的实际类型时:使用
GetType
方法。
常见问题
1. typeof
操作符使用变量会报错
2. GetType
方法对 null
对象调用会抛出异常
1 2 3 4 5 6 7 8 9 10 11
| object o = null; if (o.GetType() == typeof(Animal)) { }
if (o != null && typeof(Animal).IsAssignableFrom(o.GetType())) { }
|
3. as
操作符使用不当会导致 NullReferenceException
1 2 3 4 5 6 7 8
| (o as Animal).Speak();
Animal a = o as Animal; if (a != null) { a.Speak(); }
|