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.
Equals() Method. Type. Equals() Method is used to check whether the underlying system type of the current Type is the same as the underlying system type of the specified Object or Type.
In a class, if you overload the Equals method, you should overload the == and != operators, but it is not required. This code reports that p1 equals p2 despite the difference in z values. The difference is ignored because the compiler picks the TwoDPoint implementation of IEquatable based on the compile-time type.
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.Type
of 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.
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With