Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How c# differentiates between instance methods and virtual methods

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

Confusion comes from these 2 explanations (CLR via C# 3rd edition, Jeffrey Richter, Chapter 4 Type Fundamentals)

When calling a nonvirtual instance method, the JIT compiler locates the type object that corresponds to the type of the variable being used to make the call

And for virtual method calls

When calling a virtual instance method, the JIT compiler produces some additional code in the method, which will be executed each time the method is invoked. This code will first look in the variable being used to make the call and then follow the address to the calling object

I created 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 program produces those outputs, and Eric Lippert confirms that in his blog post (check up the comments section), I still can't figure out how compiler decides whether the method that is being called is nonvirtual instance method or virtual method.

It seems that for nonvirtual instance method calls, compiler checks the type of variable being used to call a method, and for virtual methods - type of object that is referenced by variable that is being used to make a call to the method, so I guess, there should be some way to determine whether method is nonvirtual or virtual before deciding how to execute the method.

like image 934
Michael Avatar asked Dec 26 '22 02:12

Michael


1 Answers

there should be some way to determine whether method is nonvirtual or virtual before deciding how to execute the method.

The JIT compiler is not the same as the C# compiler. By the time execution reaches the JIT compiler, the C# compiler has already decided whether or not to emit a virtual method invocation, or a non-virtual method invocation. The only thing that the Richter book is telling you is the different things the JIT compiler does to invoke virtual vs. non-virtual methods. It is not telling you how the C# compiler decides whether or not to emit virtual or non-virtual method invocations.

In general, for that, you need to look at the language specification. If the method the compiler interprets the program code as invoking is virtual, it will emit a virtual call. Otherwise, it will not. The rules of the language in this particular case, and that's the point of Jon's post, dictate the compiler emit a non-virtual method call to Derived.Foo(double) in the second invocation. This is because in this case, the compiler interprets the program code (based again on the language specification) to be invoking Derived.Foo(double). The JIT has no idea about any of that, it merely sees IL to execute a non-virtual invocation to Derived.Foo(double) with the reference d as the implicit this parameter and 10 as the first explicit parameter.

like image 100
jason Avatar answered Dec 30 '22 11:12

jason