是.NET应用程序中需要的ret指令吗?

时间:2010-09-11 22:34:15

标签: c# .net clr

我注意到C#编译器在ret方法结束时生成void指令:

.method private hidebysig static void Main(string[] args) cil managed
{
    // method body
    L_0030: ret 
} 

我已经为.NET编写了一个编译器,无论我是否发出ret语句,它都能正常工作(我已经检查了生成的IL,而且它确实不在那里)。

我只是想知道:对ret返回void所需的方法是void吗?它似乎对堆栈没有任何作用,所以我认为{{1}}方法完全没有必要,但是我想听一些对CLR有更多了解的人?

3 个答案:

答案 0 :(得分:22)

根据C#标准(ECMA-334),方法定义如下:

  

方法是实现可由对象或类执行的计算或操作的成员。   方法有一个(可能是空的)形式参数列表,一个返回值(除非方法的返回类型是   void),是静态的或非静态的。

ECMA-334; 8.7.3:方法)。

现在,CLI标准定义了以下内容:

  

不允许控制只是“通过”方法的结尾。所有路径都将终止   使用以下指令之一:ret,throw,jmp或(tail。后跟call,calli或callvirt)。

ECMA-335; 12.4,6)

这意味着,在C#中,返回void的方法不需要return语句。但是,由于C#编译器将C#代码编译为IL代码,这需要在方法结束时终止路径,因此它会发出ret来结束该方法。

答案 1 :(得分:17)

确实需要使代码可以验证。否则PEVerify将输出以下错误消息:

  

[IL]:错误:[(filename):( methodname)] [offset 0x00000000]在方法结束时没有返回

答案 2 :(得分:8)

来自Ecma-335。 (12.4,6)

  

不允许控制只是“通过”方法的结尾。所有路径都将终止   使用以下指令之一:ret,throw,jmp或(tail。后跟call,calli或callvirt)。