该代码能否正确确定两种类型是否相等?

发布于 2024-11-09 01:42:57 字数 511 浏览 0 评论 0原文

我对 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# 都可以,上面的代码是伪代码。

I'm a little foggy on System.Type versus an actual class type (like Object or XmlDocument) in .NET... will this code correctly determine if the type of a particular object is equal to a class I specify?

' 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

Which one is correct?

Bonus points if you can provide some information on what a class identifier is versus what a System.Type is. :)

Note: The language doesn't matter here, VB.NET or C# is fine, the code above is pseudocode.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

¢好甜 2024-11-16 01:42:57

首先让我们看一下您提供的三个选项:

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);
    
  • 在对象实例上,您可以检索 通过调用方法 GetType() 来获取 System.Type 元数据。它将为您提供一个与代表实际实例的类相关的System.Type 实例。这意味着,如果编译器将您的对象视为接口或基类,.GetType() 仍会为您提供该实例的最派生类型。< /p>

  • < p>您可以比较 System.Type 来检查两个对象是否是同一类的实例,但请再次注意,您的实例可以是更派生的类型;相等将失败(派生程度较高的类的 System.Type 与派生程度较低的类的不同)。

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

    BaseClass 实例 = new DerivedClass();
    
    System.Type 类型 = instance.GetType();
    
    if ((typeof(BaseClass)).IsAssignableFrom(type)) // 返回 true
    {
    }
    
  • C# 和 VB.Net 为您提供了两个运算符,使您能够即时进行类型检查,asis 会自动进行类型检索,并且优于您自己获取 System.Type。它也解释了继承:

    DerivedClass 实例 = new DerivedClass();
    
    System.Type 类型 = instance.GetType();
    
    if (实例是 BaseClass) // 返回 true
    {
    }
    
  • 如果您需要检查类型转换对象,请使用as

    DerivedClassinstance = new DerivedClass();
    
    System.Type 类型 = instance.GetType();
    
    AnotherClass another = 实例作为 AnotherClass;
    
    if (another == null) // 返回 true
    {
        // 进行适当的错误处理...抛出异常或其他东西
    }
    

    不能使用as做的是不执行正确的结果检查;问题是,如果您不检查它是否为 null 并使用它,您会得到一个 NullReferenceException,这将隐藏正确的问题(强制转换失败)。如果您确定可以进行强制转换,请使用显式强制转换:

    DerivedClassinstance = new DerivedClass();
    
    System.Type 类型 = instance.GetType();
    
    AnotherClass another = (AnotherClass)实例; // 抛出
    

    这将引发 InvalidCastException,因此代码将更容易调试。

Fist let's take a look on the three options you gave:

If myObject.GetType.Equals(MyClass)

This will probably result in a error, since the equals expects a System.Type, not a class. A class definition is not a System.Type, but you can retrieve it using the typeof operator. So you could do instance.Equals(typeof(MyClass)), which would return true if the object is of the given class.

If TypeOf(myObject) Is MyClass

Conversely, you can't use typeof with instances, only with classes, so the above code would fail. Also, the is operator automatically checks the typing so you can't do a typeof or a GetType when using it. You should go with if myObject is MyClass, which would return true if myObject can be cast to MyClass. This is different from saying that it's an instance of that type, because it could be that myObject is an instance of a class that inherits from MyClass.

If myObject.GetType() Is MyClass

Again, the is operator already checks the type on both operands, so you should go with if myObject is MyClass.


All that said, I'd like to explain the "theory" behind the type system. I'm no specialist, so I'm giving you a more practical explanation:

  • A class definition label (like MyClass) is not a System.Type. A System.Type is a metadata class that is generated by the CLR to represent the type defined by your label. To retrieve the System.Type related to a certain class definition label, use the typeof operator as follows:

    System.Type MyClassType = typeof(MyClass);
    
  • On a object instance, you can retrieve the System.Type metadata by calling the method GetType() on it. It will give you an instance of System.Type related to the class that represents the actual instance. This means that if your object is being treated by the compiler as a interface or a base class, .GetType() still gives you the most derived type for that instance.

  • You can compare System.Type in order to check if two objects are instances of the same class, but again, beware that your instance can be of a more derived type; The equality will fail (the System.Typeof a more derived class is different than that of a less derived one).

  • If you need to take inheritance into account, you can use the method IsAssignableFrom, like this:

    BaseClass instance = new DerivedClass();
    
    System.Type type = instance.GetType();
    
    if ((typeof(BaseClass)).IsAssignableFrom(type))    // returns true
    {
    }
    
  • C# and VB.Net gives you two operators that enables you to do type checking on the fly, is and as. is does automatic typing retrieval and is preferred over getting the System.Type yourself. It accounts for inheritance as well:

    DerivedClass instance = new DerivedClass();
    
    System.Type type = instance.GetType();
    
    if (instance is BaseClass)    // returns true
    {
    }
    
  • If you need to check the type and cast the object use 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
    }
    

    What you cannot do with as is not perform proper result checking; The problem is that if you don't check it for null and use it, you get an NullReferenceException, which will hide the correct problem (the cast failed). If you are sure you can do the cast, then use a explicit cast:

    DerivedClassinstance = new DerivedClass();
    
    System.Type type = instance.GetType();
    
    AnotherClass another = (AnotherClass)instance; // throws
    

    This will throw an InvalidCastException, so the code will be easier to debug.

紫竹語嫣☆ 2024-11-16 01:42:57

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

我不了解 VB,但在 C# 中,您将 isobject 一起使用,而不是它的类型 - 即

if(obj is MyClass) {...}

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

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

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

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

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

The .GetType() approach could fail if the item is null, so you might want a null check first.

I don't know about VB, but in C# you use is with the object, not it's type - i.e.

if(obj is MyClass) {...}

Another difference between is (done correctly) and GetType()/Equals - the difference here is subclasses. If the item is actually an SuperMyClass (inherited from MyClass) then Equals or == will return false - however, is will return true.

typeof is restricted to use with types, not variables - i.e. typeof(MyClass), but not typeof(obj). If you want the actual type of an object in a variable, use obj.GetType().

Personally, I would use (in C#):

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

as this does a type-check and cast once rather than twice

乙白 2024-11-16 01:42:57

综上所述,is 对于类和子类都将为 true。例如:

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 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

To sum up, is will make true for class and subclass.For example:

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

and use Equals and typeof([ClassName]) is just equal to class, not to subclass:

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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文