Will this code correctly determine if two types are equal?
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. ASystem.Type
is a metadata class that is generated by the CLR to represent the type defined by your label. To retrieve theSystem.Type
related to a certain class definition label, use thetypeof
operator as follows:System.Type MyClassType = typeof(MyClass);
On a object instance, you can retrieve the
System.Type
metadata by calling the methodGetType()
on it. It will give you an instance ofSystem.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 (theSystem.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
andas
.is
does automatic typing retrieval and is preferred over getting theSystem.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 anNullReferenceException
, 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