这段代码能否正确判断两种类型是否相等?

时间:2011-05-20 14:51:45

标签: c# .net vb.net types

我在System.Type上对于.NET中的实际类类型(如ObjectXmlDocument)有点模糊......这段代码会正确判断是否类型为特定对象是否等于我指定的类?

// Given "myObject" (unknown type), and some class type (let's say "MyClass")...

If myObject.GetType.Equals(MyClass)

If TypeOf(myObject) Is MyClass

If myObject.GetType() Is MyClass

哪一个是正确的?

如果您可以提供有关类标识符与System.Type的内容的信息,请提供一些奖励积分。 :)

注意:这里的语言没关系,VB.NET或C#没问题,上面的代码是伪代码。

3 个答案:

答案 0 :(得分:15)

如果该项为null,则.GetType()方法可能会失败,因此您可能需要先进行空检查。

我不知道VB,但是在C#中你使用is对象,而不是它的类型 - 即。

if(obj is MyClass) {...}

is(正确完成)和GetType() / Equals之间的另一个区别 - 这里的区别是子类。如果该项目实际上是SuperMyClass(继承自MyClass),那么Equals==将返回false - 但是,is将返回true

typeof仅限于与类型一起使用,而不是变量 - 即typeof(MyClass),而不是typeof(obj)。如果您想要变量中对象的实际类型,请使用obj.GetType()

就个人而言,我会使用(在C#中):

var typed = obj as MyClass;
if(typed != null) {
    // do something interesting with typed
}

因为这会进行类型检查并进行一次而不是两次

答案 1 :(得分:14)

Fist让我们来看看你给出的三个选项:

If myObject.GetType.Equals(MyClass)

这可能会导致错误,因为equals需要System.Type,而不是类。类定义不是System.Type,但您可以使用typeof运算符检索它。所以你可以做instance.Equals(typeof(MyClass)),如果对象属于给定的类,它将返回true。

If TypeOf(myObject) Is MyClass

相反,您不能将typeof用于实例,只能用于类,因此上述代码将失败。此外,is运算符会自动检查输入内容,因此您在使用时无法执行typeofGetType。您应该使用if myObject is MyClass,如果myObject 可以转换为MyClass ,则返回true。这与说它是该类型的实例不同,因为它可能是myObject是继承自MyClass的类的实例。

If myObject.GetType() Is MyClass

同样,is运算符已经检查了两个操作数上的类型,因此您应该使用if myObject is MyClass


所有这一切,我想解释类型系统背后的“理论”。我不是专家,所以我给你一个更实际的解释:

  • 类定义标签(如MyClass)不是System.Type。 System.Type是由CLR生成的元数据类,用于表示标签定义的类型。要检索与某个类定义标签相关的System.Type,请使用typeof运算符,如下所示:

代码:

System.Type MyClassType = typeof(MyClass);
  • 在对象实例上,您可以通过调用System.Type方法来检索GetType()元数据。它将为您提供与表示实际实例的类相关的System.Type实例。这意味着如果您的对象被编译器视为接口或基类,.GetType()仍然为您提供该实例的最多派生类型。

  • 您可以比较System.Type以检查两个对象是否是同一个类的实例,但同样要注意您的实例可以是更多派生类型;相等性将失败(更加派生的类的System.Type与较少派生的类的BaseClass instance = new DerivedClass(); System.Type type = instance.GetType(); if ((typeof(BaseClass)).IsAssignableFrom(type)) // returns true { } 不同。

  • 如果您需要考虑继承,可以使用方法IsAssignableFrom,如下所示:

代码:

is
  • C#和VB.Net为您提供了两个运算符,使您可以即时进行类型检查,asisSystem.Type执行自动输入检索,并且比自己获取DerivedClass instance = new DerivedClass(); System.Type type = instance.GetType(); if (instance is BaseClass) // returns true { } 更受欢迎。它也说明了继承:

代码:

as
  • 如果您需要检查类型,请使用DerivedClassinstance = new DerivedClass(); System.Type type = instance.GetType(); AnotherClass another = instance as AnotherClass; if (another == null) // returns true { // Do proper error treatment... throw an exception or something } 投射对象:

代码:

as

无法NullReferenceException执行的操作未执行正确的结果检查;问题是,如果你没有检查它并使用它,你得到一个DerivedClassinstance = new DerivedClass(); System.Type type = instance.GetType(); AnotherClass another = (AnotherClass)instance; // throws ,这将隐藏正确的问题(转换失败)。如果您确定可以进行演员表演,那么请使用明确的演员:

InvalidCastException

这将抛出{{1}},因此代码将更容易调试。

答案 2 :(得分:0)

总而言之,is将对类和子类生效。例如:

class B:Program{}
class Program{}
Program a = new Program();
B b = new B();
if (b is Program) ; // true
if (a is Program) ; // true
if (a is B) ; // false
if (b is B) ; //false

并使用Equals和typeof([ClassName])等于class,而不是子类:

class B:Program{}
class Program{}
Program a = new Program();
B b = new B();
if (b.GetType() == typeof(program)) ; // false
if (b.GetType() == typeof(B)) ; // true
if (a.GetType() == typeof(B)) ; // false
if (a.GetType() == typeof(Program)) ; //true