当调用静态方法时,CLR如何管理?

Tan*_*man 4 c#

我有静态类,有静态方法,如下所示:

public static StaticTest
{
   public static void DoSomeWork()
   {
    /// Do Some work
   }
}
Run Code Online (Sandbox Code Playgroud)

DoSomeWork()函数被调用时,如何CLR管理功能的引用,因为它是明显的静态类的实例不能创建?

在这种情况下调用函数的场景背后的机制是什么?

xan*_*tos 6

假设你有:

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

    public static void Fiz()
    {
        // instance
    }
}
Run Code Online (Sandbox Code Playgroud)

你也是:

var temp = new Foo();
Foo.Fiz();
temp.Bar();
Run Code Online (Sandbox Code Playgroud)

你的代码被翻译成类似的东西:

var temp = new Foo();
Foo.Fiz();
Foo.Bar(temp);
Run Code Online (Sandbox Code Playgroud)

这个被翻译成类的一个隐藏的参数(第一个)。在英特尔的 C++ 中,这称为thiscall 调用约定。对于静态函数,根本就没有这个参数。

如果您在该代码上打开反汇编功能,您将看到它类似于:

            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  
Run Code Online (Sandbox Code Playgroud)

正如你所看到的,Foo.Fiz是一个直接的call 00007FFBD46ECA40,而temp.bar()第一个检查null(我认为,mov+ cmp),然后放入rcx引用并执行call

  • 打败我,这或多或少是我要指出的。也许另一个有用的信息是 C# 编译器发出 callvirt 指令来检查实例方法的接收器并发出对静态方法的调用,但是 [您可以很好地编写使用 call 并将空接收器传递给实例方法](http://blog.paranoidcoding.com/2015/03/11/observing-a-null-this.html)。从某种意义上说,静态方法并不特殊,实例方法是一种特殊的静态方法。 (3认同)

Dar*_*rov 5

当CLR加载包含静态成员的程序集时,这些成员将被放置在内存中名为High Frequency Heap的专用空间中.高频堆中的对象永远不会收集垃圾,以确保静态变量在应用程序的整个生命周期中都可用.

  • *类名称只是对这些方法进行分组的便捷方式.从技术上讲,它不是必需的*Ehm ......它过于简单了...这个"分组"有一个"目的"......静态构造函数和字段初始化程序"连接"到静态类"拥有"该方法,另外还有可见性规则(公共/私人). (2认同)