Interesting rewriting of the GetType () method

Source: Internet
Author: User
Tags mscorlib

Recently I chatted with my colleagues about. net interview questions. One interview question is whether GetType () can be reloaded. The answer is no. The reason is that GetType () is not Virtual, so it cannot be overloaded. GetType () is not reloaded to ensure type security. One of my colleagues suddenly wondered whether to use new to rewrite the GetType () method. The following code:
 

 namespace test
{
public class Employee
{
public new Type GetType()
{
return typeof(string);
}
}

public class Program
{
public static void Main()
{
Employee emp = new Employee();
Console.WriteLine("hello {0}", emp.GetType().Name);
//Object obj = emp;
//Console.WriteLine("obj is System.String = {0}", obj is System.String);
//Console.WriteLine("obj is test.Employee = {0}", obj is test.Employee);
Console.ReadKey();
}
}
}

Run this program and it outputs:

Hello String

Ah! Can we change the type of a class at will? Think about it, it's just a blind eye. Let's verify it. Slightly change the code and remove the comments before these lines:

Object obj = emp;
Console. WriteLine ("obj is System. String = {0}", obj is System. String );
Console. WriteLine ("obj is test. Employee = {0}", obj is test. Employee );
Run again, and the output is:

Hello String

Obj is System. String = false

Obj is test. Employee = true

What does this mean? It indicates that the emp type is still the Employee type in the CLR's opinion and will not be changed by the newly written GetType () method. Why? Let's take a look at the Main function's IL code:

 

 

 

 

 .method public hidebysig static void Main() cil managed
{
.entrypoint
.maxstack 3
.locals init (
[0] class test.Employee emp,
[1] object obj)
L_0000: nop
L_0001: newobj instance void test.Employee::.ctor()
L_0006: stloc.0
L_0007: ldloc.0
L_0008: stloc.1
L_0009: ldstr "hello {0}"
L_000e: ldloc.0
L_000f: callvirt instance class [mscorlib]System.Type test.Employee::GetType()
L_0014: callvirt instance string [mscorlib]System.Reflection.MemberInfo::get_Name()
L_0019: call void [mscorlib]System.Console::WriteLine(string, object)
L_001e: nop
L_001f: ldstr "obj is System.String = {0}"
L_0024: ldloc.1
L_0025: isinst string
L_002a: ldnull
L_002b: cgt.un
L_002d: box bool
L_0032: call void [mscorlib]System.Console::WriteLine(string, object)
L_0037: nop
L_0038: ldstr "obj is test.Employee = {0}"
L_003d: ldloc.1
L_003e: isinst test.Employee
L_0043: ldnull
L_0044: cgt.un
L_0046: box bool
L_004b: call void [mscorlib]System.Console::WriteLine(string, object)
L_0050: nop
L_0051: call valuetype [mscorlib]System.ConsoleKeyInfo [mscorlib]System.Console::ReadKey()
L_0056: pop
L_0057: ret
}

 

Note the line L_000f: The IL code generated by the compiler is the callvirt command. The callvirt command correctly discovers the Virtual Methods of the base class functions and the overload methods of the subclass, and correctly calls the appropriate methods. The called function is the GetType () method of the Employee class. So the output is hello String.

 

In addition, pay attention to the row L_0025: isinst string, which is used to determine whether the current object in the stack is of the string type.

There is also L_003e: isinst test. Employee, which is used to determine whether the current object in the stack is of the test. Employee type.
These two commands are previously the ldloc.1 command, which means to put the local variable obj into the stack, so obj is the current object in the isinst stack.

 

Why didn't we overwrite the original GetType () method of the object in the new GetType () method we wrote?

This is because each method has its own method signature. The original GetType () method of the object is in the method table of metadata, and there is a unique method signature. The new GetType () method we write is also in the method table in metadata, and there is also a method signature, which uniquely identifies each method. When viewing the type of an object, CLR uses the original GetType () method signature of the object to find the GetType () method, so that no error method is called. The new GetType () method we write ourselves will not be called when checking the type. The new GetType () method we write can only be called in the callvirt command.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.