为什么C#预先绑定局部变量?

GWL*_*osa 7 .net c# clr

所以在C#中,您可能有以下代码:

void DoSomething()
{
    //some code.
    int x = 5;
    //some more code.
}
Run Code Online (Sandbox Code Playgroud)

一旦输入DoSomething,CLR就会为int x设置空间.为什么它不等到它到达int x = 5的行呢?特别是因为即使绑定了x,它也不会让你实际使用它,直到到达那条线为止?

Eri*_*ert 13

一进入DoSomething,CLR 就会为其设置空间int x.为什么它不等到它到达线上int x = 5

这个问题无法回答,因为整个问题建立在一个不正确的前提上.局部变量的存储空间可能是:

  • 首次输入方法时分配
  • 当控制到达声明时分配
  • 控件到达初始化时分配(假设初始化和声明不同)
  • 在特殊情况下分配 - 例如,如果本地是lambda的封闭本地,或者在迭代器块中,或在异步块中,分配本地存储的方式和时间可能会变得复杂
  • 完全否定; 如果从未使用过本地,则可能不会首先分配本地.

C#编译器和jit编译器肯定会确保以正确的方式分配本地存储,并尝试确保它是高效的.他们如何选择这样做取决于具体情况.预先分配空间可能更有效,只要变量正在使用,分配它可能更有效; 在选择局部变量的寿命时,允许广泛的抖动.如果抖动可以在不违反程序正确性的情况下这样做,则允许局部变量比它们的范围更长和更短.

由于问题的前提是不正确的,因此问题没有答案.问一个更好的问题.

  • @IgbyLargeman:当你将鼠标悬停在upvote上时,你得到的提示是"这个答案很有用",而不是"这个答案回答了被问到的问题".如果指出一个问题以不正确的前提为基础是有用的*那么就没有矛盾了. (2认同)

And*_*ykh 10

您可能知道,从C#代码到本机代码有几个步骤:

  • 从C#编译为IL(字节码)
  • 从字节码到本机代码的JITting

C#对内存分配的时间没有任何控制,你称之为绑定,这完全取决于JIT.把它放在一边让我们看看C#的控件什么.C#生成的字节代码必须符合CLR ECMA标准.如果我们转到分区1的第12.1.6.1节,我们将看到,标准定义了局部变量的home 位于方法头中.由于方法签名通常会出现在列表中方法的开头,因此您会得到一个(错误的)印象,即它们是预先绑定的,实际上可能是也可能不是.

但是,如果您正在查看已编译的本机代码,则结果可能因平台而异.历史上,在CPU堆栈上为局部变量分配空间是由更改堆栈指针的单个CPU指令完成的.如果你想通过变量进行变量,那么你将有许多指令,每个变量一个,效率较低.这就是为什么,至少在x86上你会看到CPU堆栈上的空间是预先分配的.