How C # distinguishes instance methods and virtual methods

So basically, I want to understand what are the general steps that the C # compiler takes to determine if the method that is being called is not a virtual instance method or a virtual method.

The confusion comes from these two explanations (CLR through 3rd Edition C #, Jeffrey Richter, Fundamentals of Chapter 4)

When invoking a non-virtual instance method, the JIT compiler finds a type object that matches the type of the variable being used to call

And for virtual method calls

When invoking a virtual instance method, the JIT compiler generates some additional code in the method, which will be executed every time the method is called. This code will first look in the variable used to make the call, and then follow the address of the caller

I created a small test project

class Program { static void Main(string[] args) { Parent p = new Derived(); p.Foo(10); // Outputs Derived.Foo(int x) Derived d = new Derived(); d.Foo(10); // Outputs Derived.Foo(double y) } } internal class Parent { public virtual void Foo(int x) { Console.WriteLine("Parent.Foo(int x"); } } internal class Derived: Parent { public override void Foo(int x) { Console.WriteLine("Derived.Foo(int x)"); } public void Foo(double y) { Console.WriteLine("Derived.Foo(double y)"); } } 

While Jon Skeet has a blog post explaining why the program produces these outputs, and Eric Lippert confirms that in his blog post (check the comment section), I still can’t understand how the compiler decides is whether the method that is being called is not a virtual instance method or a virtual method.

It seems that when calling the nonvirtual method of the instance, the compiler checks the type of the variable used to call the method, and for virtual methods, the type of the object referenced by the variable that is used to call the method, so I think there should be some way to determine whether the method is not virtual or virtual before deciding how to execute the method.

+4
source share
1 answer

there must be some way to determine if the method is not virtual or virtual before deciding how to execute the method.

The JIT compiler does not match the C # compiler. By the time execution reaches the JIT compiler, the C # compiler has already decided whether to invoke a virtual method call or a non-virtual method call. The only thing Richter's book tells you is the different things that the JIT compiler does to invoke virtual and non-virtual methods. This does not tell you how the C # compiler decides whether to issue calls to virtual or non-virtual methods.

In general, for this you need to look at the language specification. If the method that the compiler interprets the program code as the caller is virtual, it will issue a virtual call. Otherwise this will not happen. The rules of the language are in this particular case and that John’s point post dictates to the compiler to emit a call to the non-virtual method Derived.Foo(double) in the second call. This is because in this case, the compiler interprets the program code (based on the language specification) to call Derived.Foo(double) . The JIT knows nothing about this, it just sees that IL is making a non-virtual call in Derived.Foo(double) with the d link as an implicit parameter of this and 10 as the first explicit parameter.

+10
source

Source: https://habr.com/ru/post/1483867/


All Articles