4

I have static class having static methods as shown below:

public static StaticTest
{
   public static void DoSomeWork()
   {
    /// Do Some work
   }
}

When DoSomeWork() function is called, how does CLR manage the function references as it is obvious that an instance of static class cannot be created?

What is the mechanism behind the scene to call the function in this case?

Radiodef
  • 37,180
  • 14
  • 90
  • 125
Tanzeel ur Rehman
  • 429
  • 2
  • 6
  • 18
  • If you are doubtful about how to call a static function, you just have to call it using your `class` reference since `static` classes cannot be instantiated. Its like `StaticTest.DoSomeWork()`. – Dhrumil Apr 18 '15 at 05:30
  • I know how to call the static function. I am confused about the CLR mechanism to manage static functions. according to my understanding when non static functions are called instance of the class is to be created first.they are called using the instance of the class and the instance knows about the function reference where is it placed and called the function. So my confusion is about the process how it calls the static functions with in the static class – Tanzeel ur Rehman Apr 18 '15 at 05:38
  • 2
    You have the wrong mental model how methods work. There is only ever one "instance" of a method, it is used by all of the objects of a class. The CLR doesn't distinguish between a static and an instance method, they just have one property. The address of the machine code for the method. Ultimately the target of the CALL instruction. What's special about an instance method over a static method is an extra argument. You don't write that extra argument in your code, but commonly use it inside the method. It is *this*. Also the mechanism that makes extension methods work. – Hans Passant Apr 18 '15 at 14:12
  • Related post - [What's a “static method” in C#?](https://stackoverflow.com/q/4124102/465053) – RBT Feb 07 '19 at 11:02

4 Answers4

8

When the CLR loads an assembly containing static members, those members are placed in a dedicated space in memory called High Frequency Heap. Objects in the High-Frequency Heap are never Garbage collected to make sure that the static variables are available throughout the lifetime of the application.

Darin Dimitrov
  • 1,023,142
  • 271
  • 3,287
  • 2,928
  • Thanks, as i understood your answer, it means all the static variables are static methods are loaded in high frequency heap. So why we use className.functionName() to call the function. Can't we access them directly as CLR knows about the high frequency heap – Tanzeel ur Rehman Apr 18 '15 at 05:48
  • The class name is just a convenient way to group those methods. Technically it is not required. – Darin Dimitrov Apr 18 '15 at 05:52
  • 1
    Indeed, a common use case of not referencing the static class name is extension methods – jdphenix Apr 18 '15 at 05:52
  • @DarinDimitrov and jdbphenix thanks. it is now clear. can you suggest me a book or web url where i can understand the in and out of CLR, – Tanzeel ur Rehman Apr 18 '15 at 05:57
  • @Tanzeel, here'e a good reference on MSDN: https://msdn.microsoft.com/en-us/magazine/cc163791.aspx – Darin Dimitrov Apr 18 '15 at 06:01
  • 2
    *The class name is just a convenient way to group those methods. Technically it is not required* Ehm... it is oversimplifying... This "grouping" has a "purpose"... Static constructor and field initializers are "connected" to the static class "owning" the method, plus there are the visibility rules (public/private). – xanatos Apr 18 '15 at 06:14
7

Let's say you have:

class Foo
{
    public void Bar()
    {
        // instance
    }

    public static void Fiz()
    {
        // instance
    }
}

And you do:

var temp = new Foo();
Foo.Fiz();
temp.Bar();

Your code is translated to something like:

var temp = new Foo();
Foo.Fiz();
Foo.Bar(temp);

The this is translated as an hidden parameter of the class (the first one). In C++ for Intel this is called the thiscall calling convention. For static functions, simply there isn't this parameter.

If you open the Disassembly function on that code you'll see that it is something like:

            var temp = new Foo();
00007FFBD48042EC  lea         rcx,[7FFBD48563D8h]  
00007FFBD48042F3  call        00007FFC33E42400  
00007FFBD48042F8  mov         qword ptr [rsp+2B0h],rax  
00007FFBD4804300  mov         rax,qword ptr [rsp+2B0h]  
00007FFBD4804308  mov         qword ptr [rsp+2B8h],rax  
00007FFBD4804310  mov         rcx,qword ptr [rsp+2B8h]  
00007FFBD4804318  call        00007FFBD46ECA48  
00007FFBD480431D  mov         r11,qword ptr [rsp+2B8h]  
00007FFBD4804325  mov         qword ptr [rsp+30h],r11  
            Foo.Fiz();
00007FFBD480432A  call        00007FFBD46ECA40  
            temp.Bar();
00007FFBD480432F  mov         r11,qword ptr [rsp+30h]  
00007FFBD4804334  cmp         byte ptr [r11],0  
00007FFBD4804338  mov         rcx,qword ptr [rsp+30h]  
00007FFBD480433D  call        00007FFBD46ECA38  

As you can see the Foo.Fiz is a direct call 00007FFBD46ECA40, while the temp.bar() first does a check for the null (I think, the mov + cmp), then puts in rcx the reference and does the call

xanatos
  • 109,618
  • 12
  • 197
  • 280
  • 3
    Beat me to it, this is more or less what I was going to point out. Perhaps another useful piece of information is that the C# compiler emits a callvirt instruction to null check the receiver of an instance method and a emits call for static methods, but [you could very well write IL that uses call and passes a null receiver to an instance method](http://blog.paranoidcoding.com/2015/03/11/observing-a-null-this.html). In a sense static methods are not special, it is instance methods that are a special kind of static method. – Mike Zboray Apr 18 '15 at 06:23
3

When a method starts executing, CLR identifies the types used in the method and ensures that referred assemblies are loaded.

Then it creates "Type Objects" for each referenced type in the method (if they are not existing).

Each type object contains Type Object Pointer, Sync Block Index, static fields and a Method table (which contains one entry for each method of the type).

public void DoSomething()
{
 InstanceClass objectInstance =  new InstanceClass();
 objectInstance.MethodName();
 StaticClass.MethodName();
 // i.e.here clr creates Type Objects for Instance class and StaticClass in the heap
}

enter image description here

When the new operator is used to create an object of a class, CLR automatically creates a Type Object Pointer in the instance of that class and initializes it to refer the corresponding Type Object.

When an INSTANCE (non virtual) method is called, i.e. objectInstance.MethodName(), CLR identifies the Type Object based on the variable type used and finds the method in the type object's method table and then JIT's the method.

When a static method is called i.e StaticTest.DoSomeWork(), CLR (JIT Compiler) will identify the "Type Object" of the static class based on the class name and the JIT compiler looks for the method in the method table of the corresponding Type Object and then JIT's the method.

Nisse Engström
  • 4,738
  • 23
  • 27
  • 42
Abhilash NK
  • 501
  • 5
  • 5
  • So basically - an instanced method needs to create on and use the stack, but a static method is all contained on the heap? – jamheadart Nov 21 '22 at 15:17
1

The function body exists in the assembly as a set of IL instructions. When you call that function, the IL resulting is something like:

call     void[assembly]StaticTest:DoSomeWork()

so the runtime looks into "assembly" for the IL body of DoSomeWork, JIT and execute it. By another point of view, static function are just as regular function, but without a "this" reference to work with.

Felice Pollano
  • 32,832
  • 9
  • 75
  • 115