类型检查:typeof、GetType 还是 is?

类型检查:typeof、GetType 还是 is?

技术背景

在 C# 编程中,类型检查是一项常见的操作,用于确定对象的类型。typeofGetTypeis 是三种不同的类型检查方式,它们在不同的场景下发挥着作用。了解它们的区别和适用场景,能够帮助开发者更高效地进行类型检查和编程。

实现步骤

1. typeof 操作符

typeof 操作符用于在编译时获取类型信息,它接受一个类型名称作为参数。例如:

1
Type t = typeof(int);

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; // true

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); // 返回 "Animal"
string result2 = Foo(definitely_a_dog); // 返回 "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 类的 IsInstanceOfTypeIsAssignableFromIsSubClassOf 方法进行类型检查。例如:

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); // true
bool result2 = typeof(Animal).IsAssignableFrom(dog.GetType()); // true
bool result3 = dog.GetType().IsSubclassOf(typeof(Animal)); // true

核心代码

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)); // false
Console.WriteLine(a is Animal); // true
Console.WriteLine(a.GetType() == typeof(Dog)); // true
Console.WriteLine(a is Dog); // true
}

Dog spot = new Dog();
PrintTypes(spot);

// typeof(T) 示例
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)); // 输出 "Animal"
Console.WriteLine(Foo(definitely_a_dog)); // 输出 "Dog"

// as 操作符示例
object obj = new Foo();
Foo foo = obj as Foo;
if (foo != null)
{
// 执行代码
}

// C# 7+ 模式匹配示例
object obj1 = 10;
if (obj1 is int integerValue)
{
integerValue++;
}

// Type 类方法示例
public class Animal { }
public interface ITrainable { }
public class Dog : Animal, ITrainable { }

Animal dog = new Dog();

Console.WriteLine(typeof(Animal).IsInstanceOfType(dog)); // true
Console.WriteLine(typeof(Animal).IsAssignableFrom(dog.GetType())); // true
Console.WriteLine(dog.GetType().IsSubclassOf(typeof(Animal))); // true

最佳实践

  • 仅需判断对象是否为某类型时:使用 is 关键字,它简洁且能处理继承关系。
  • 需要将对象作为特定类型处理,但不确定对象类型时:使用 as 操作符并检查 null,这样可以避免多次类型检查。
  • 需要在编译时获取类型信息时:使用 typeof 操作符。
  • 需要在运行时获取对象的实际类型时:使用 GetType 方法。

常见问题

1. typeof 操作符使用变量会报错

1
Type t = typeof(obj1); // 错误,typeof 只能接受类型名称,不能接受变量

2. GetType 方法对 null 对象调用会抛出异常

1
2
3
4
5
6
7
8
9
10
11
object o = null;
if (o.GetType() == typeof(Animal)) // 会抛出 NullReferenceException
{
// 代码
}

// 正确做法
if (o != null && typeof(Animal).IsAssignableFrom(o.GetType()))
{
// 代码
}

3. as 操作符使用不当会导致 NullReferenceException

1
2
3
4
5
6
7
8
(o as Animal).Speak(); // 如果 o 不是 Animal 类型,会抛出 NullReferenceException

// 正确做法
Animal a = o as Animal;
if (a != null)
{
a.Speak();
}

类型检查:typeof、GetType 还是 is?
https://119291.xyz/posts/type-checking-typeof-gettype-or-is/
作者
ww
发布于
2025年5月26日
许可协议