CSharp - c#类型检查使用typeof, GetType, 还是 is?

  显示原文与译文双语对照的内容

我见过很多人使用以下代码:


Type t = typeof(obj1);
if (t == typeof(int))
//Some code here

但我知道你也可以这样做:


if (obj1.GetType() == typeof(int))
//Some code here

或者这个:


if (obj1 is int)
//Some code here

个人来说,我觉得最后一个是最干净的,但我是否缺少了什么? 哪一个最好使用,还是个人偏好?

时间:

都是不同的。

  • typeof 接受类型名称( 你在编译时指定的) 。
  • GetType 获取实例的运行时类型。
  • 如果实例位于继承树中,is 返回真。

例子


class Animal { } 
class Dog : Animal { }

void PrintTypes(Animal a) { 
 print(a.GetType() == typeof(Animal))//false 
 print(a is Animal)//true 
 print(a.GetType() == typeof(Dog))//true
}

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


typeof(T)它也在编译时解析?

是。T 总是表达式的类型。 记住,一般方法基本上是一系列具有适当类型的方法。 例如:


string Foo<T>(T object) { return typeof(T).Name; }

Animal probably_a_dog = new Dog();
Dog definitely_a_dog = new Dog();

Foo(probably_a_dog);//this calls Foo<Animal> and returns"Animal"
Foo<Animal>(probably_a_dog);//this is exactly the same as 上面
Foo<Dog>(probably_a_dog);//!!! This will not compile. The parameter expects a Dog, you cannot pass in an Animal.

Foo(definitely_a_dog);//this calls Foo<Dog> and returns"Dog"
Foo<Dog>(definitely_a_dog);//this is exactly the same as 上面.
Foo<Animal>(definitely_a_dog);//this calls Foo<Animal> and returns"Animal". 
Foo((Animal)definitely_a_dog);//this does the same as 上面, returns"Animal"

使用 typeof 当你想要的类型编译时间。 使用 GetType 当你想要在执行时间类型。 很少有情况可以使用 is,因为它是强制转换的,在大多数情况下,你最终会强制转换变量。

你还没有考虑( 尤其是如果你要将一个对象转换为你所找到的类型)的第四个选项,即使用 as


Foo foo = obj as Foo;

if (foo!= null)
//your code here

这只使用铸而这种方法:


if (obj is Foo)
 Foo foo = (Foo)obj;

需要磅的

1.


Type t = typeof(obj1);
if (t == typeof(int))

这是非法的,因为typeof只对类型有效,不适用于变量。 我假设obj1是一个变量。 因此,以这种方式,typeof是静态的,它的工作在编译时而不是运行时。

2.


if (obj1.GetType() == typeof(int))

如果obj1的类型为 int,则为真。 如果obj1从int派生,则条件条件为 false 。

3.


if (obj1 is int)

如果obj1是一个 int,或者它是从名为int的类派生的,或者它实现了一个名为int的接口。


Type t = typeof(obj1);
if (t == typeof(int))
//Some code here

这是一个错误。C# 中的typeof运算符只能接受类型名,而不能接受对象。


if (obj1.GetType() == typeof(int))
//Some code here

这将会工作,但可能不如你预期的那样。 for youhave价值链类型、as it ismissiriya出版物可以接受,若非references类型,即如果只在《示范 return true 萨米确切类型、not如同另外inthe随机挑选的分级结构。 举个例子:


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");
}

这将打印 "o is something else" ,因为 o的类型是 Dog,而不是 Animal 。 你可以做这项工作,但是,如果你使用 IsAssignableFromType 类的方法。


if(typeof(Animal).IsAssignableFrom(o.GetType()))//note use of tested type
 Console.WriteLine("o is an animal");

这项技术仍然有一个主要问题。 如果变量为空,对 GetType()的调用将引发 NullReferenceException 。 为了使它正常工作,你需要:


if(o!= null && typeof(Animal).IsAssignableFrom(o.GetType()))
 Console.WriteLine("o is an animal");

有了这个,你就有了 is 关键字的等价行为。 因此,如果这是你想要的行为,你应该使用 is 关键字,它更易读更高效。


if(o is Animal)
 Console.WriteLine("o is an animal");

仍然可能是更好的,是使用 as 关键字,如果你需要做的不仅仅是检查一些某种类型,但也使用对象类型。

例如不要这样做:


if(o is Animal)
 ((Animal)o).Speak();

相反,执行以下操作:


Animal a = o as Animal;
if(a!= null)
 a.Speak();

我有一个 Type -property比较,不能使用 is ( 像 my_type is _BaseTypetoLookFor ), 但我可以使用这些:


base_type.IsInstanceOfType(derived_object);
base_type.IsAssignableFrom(derived_type);
derived_type.IsSubClassOf(base_type);

注意,IsInstanceOfTypeIsAssignableFrom 在比较相同类型时返回 true,其中IsSubClassOf将返回 falseIsSubclassOf 不能在接口上工作,而其他两个。 ( 请参见这个问题并回答 。)


class Dog : Animal{}
Animal dog = new Dog();

Animal.IsInstanceOfType(dog);//true
Dog.IsInstanceOfType(dog);//true

Animal.IsAssignableFrom(dog.GetType());//true
Dog.IsAssignableFrom(dog.GetType());//true

dog.GetType().(IsSubClassOf(Animal));//true
dog.GetType().(IsSubClassOf(Dog));//false

我喜欢

也就是说,如果你使用的是,你不可能正确使用继承。

假设此人:实体和那个动物: 实体。提要是实体中的虚方法( 使Neil高兴)


class Person
{
//A Person should be able to Feed
//another Entity, but they way he feeds
//each is different
 public override void Feed( Entity e )
 {
 if( e is Person )
 {
//feed me
 }
 else if( e is Animal )
 {
//ruff
 }
 }
}

更改为


class Person
{
 public override void Feed( Person p )
 {
//feed the person
 }
 public override void Feed( Animal a )
 {
//feed the animal
 }
}

这取决于我在做什么。 如果我需要一个布尔值( 确定是否将转换为 int ),我将使用 is 。 如果我真的需要某种类型的( 也就是说,传递给其他方法),我将使用 GetType()

...