开发者

GetType returns diffent information than is operator uses

开发者 https://www.devze.com 2023-01-18 06:00 出处:网络
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. C

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

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号