什么都不返回或返回void – C#在void Function()调用结束时究竟做了什么?

考虑以下C#函数:

void DoWork() { ... } 

C#文档说明:

当用作方法的返回类型时,void指定该方法不返回值

这似乎是直截了当的,在大多数情况下,这适合作为公平的定义。

然而,对于许多低级语言(即C),“void”具有略微不同的含义。 具体来说,所有代码块都必须返回一些内容 。 因此, void是空指针的表示,它表示“无”。 在这种情况下,您不需要在代码中包含return语句,因为任何不返回值的块语句都会自动返回空指针。

这是C#所做的,或者当调用void函数时,它是否执行一段代码并返回甚至没有包含void值的指针?

首先,C#被编译成IL,因此JIT后的最终表示可能会有所不同。

使用void方法,IL中的方法签名将标记为void ,并且ret操作码仍将存在。 这意味着,从IL的角度来看,调用堆栈上的“返回”值可能存在也可能不存在,但它永远不会被复制并在调用站点上使用。 ret操作码只会返回一个返回值(如果存在),并且这不需要存在于void返回方法中,因此在许多情况下,即使在低级概念角度, 它也不会返回任何内容

然而,对于许多低级语言(即C),“void”具有略微不同的含义。 具体来说,所有代码块都必须返回一些内容。

在CLR中情况并非如此。 void方法可以真正返回任何内容,因为ret操作码不允许返回任何内容。 请参阅OpCodes.Ret

从当前方法返回,将返回值(如果存在)从被调用者的评估堆栈推送到调用者的评估堆栈。

如果此规范与官方语言规范类似,则未定义void方法/函数的返回值,这意味着,如果您需要null值,则最好显式使用null而不是此值。

在C中,使用void函数的返回值来获取null是不好的forms。 这是因为:

  1. 对下一个人来说会很困惑,
  2. 这没有道理。 如果要null,请使用null。 如果希望void函数根据其计算返回值,请不要使用void返回类型,和
  3. 最重要的是,由于它在技术上是不正确的,即使代码在编译器的当前版本上编译,它在将来的版本中可能根本不编译,或者行为可能意外地改变。

编辑:此外,如果单词assembly不会让你的脊椎冷颤…

在C编译的底层x86汇编代码中,void函数确实无法返回任何内容。 从函数返回值的想法实际上是由编译器实现的,因此如果您告诉编译器您不希望某些东西具有返回值,那么就不会有。

这个文档很好地解释了ret指令以及它如何适应子程序调用约定(遗憾的是, id元素在本文档中很少见,所以需要一些滚动。但它就在那里。在页面上搜索ret )。

在MSIL中,Ret可以选择返回一个值,因此void方法不会返回任何内容。 请参阅http://msdn.microsoft.com/en-us/library/system.reflection.emit.opcodes.ret.aspx

当MSIL被JIT编辑时,我不确定如何处理这个问题。