GetType returns diffent information than is operator uses
Cannot explain what is going on the following program. GetType is returning the type I want to return and not the original one. Does that mean we cannot rely on GetType? is operator is right though. Can anybody please explain it in detail?
using System;
namespace ConsoleApplication2开发者_JS百科
{
public class MyClass
{
public Type GetType()
{
return typeof(Program);
}
}
class Program
{
static void Main(string[] args)
{
MyClass mc = new MyClass();
if (mc.GetType() == typeof(Program))
{
Console.WriteLine("Confused.");
}
if(mc is Program)
{
Console.WriteLine(mc.GetType()); // Don't get inside the if. Why?
}
}
}
}
Update: I am reading the book CLR via C# 3rd edition. In chapter 4 (2nd page) when it explains different methods in System.Object it says
"The GetType method is nonvirtual, which prevents a class overriding this method and lying about its type"
While I agree about the first statement, I am lying about MyClass type. ain't I?
is operator implemented in terms of as operator and finally use isinst IL instruction. And of course this instruction don't know about your not virtual GetType method that you define in some class in your inheritance hierarchy.
To understand this "confusing" behavior lets "implement" our own version of the "is operator":
public class MyClass
{
public Type GetType()
{
return typeof(Program);
}
}
class Program {
//this is oversimplified implementation,
//but I want to show the main differences
public static bool IsInstOf(object o, Type t)
{
//calling GetType on System.Object
return o.GetType().IsAssignableFrom(t);
}
static void Main(string[] args)
{
MyClass mc = new MyClass();
//calling MyClass non-virtual version for GetType method
if (mc.GetType() == typeof(Program))
{
//Yep, this condition is true
Console.WriteLine("Not surprised!");
}
//Calling System.Object non-virtual version for GetType method
if (IsInstOf(mc, typeof(Program)))
{
//Nope, this condition isn't met!
//because mc.GetType() != ((object)mc).GetType()!
}
Console.ReadLine();
}
}
Please take care of the warning, as they do exists for reasons. Your code compiled with the following warning:
Warning 1 'ConsoleApplication2.MyClass.GetType()' hides inherited member 'object.GetType()'. Use the new keyword if hiding was intended.
which means GetType()
is non-virtual and you are writing new unrelated method of GetType()
that CLR will never call it.
Object.GetType
is not a virtual method. So mc is MyClass
and effectively calls Object.GetType
and not your method.
is checks the actual runtime type of your variable. The compiler don't care that you have defined a method called GetType() that returns another Type
. It still knows that the actuall type of your variable is MyClass
.
What exactly are you trying to accomplish here? Why do you need your MyClass
class to impersonate the Program
class?
It will only be true if:
if (mc is MyClass) { ... }
According to the documentation, the 'is' operator is not overloadable. That is why it is probably not getting into your second 'if' statement.
Check out this page from MSDN: http://msdn.microsoft.com/en-us/library/8edha89s%28v=VS.80%29.aspx
精彩评论