为什么C#不允许我将void方法作为return语句的一部分?
我很好奇,如果有一个合法的原因,为什么C#不支持调用void方法作为返回语句的一部分,当调用方法的返回types也是void。
public void MethodA() { return; } public void MethodB() { return MethodA(); }
所以我们通常会看到这个:
public void MethodMeh() { if (expression) { MethodA(); return; } // Do more stuff }
…当我们可以用这个代替时:
public void MethodAwesome() { if (expression) return MethodA(); // Do more stuff }
这是由于C#如何处理无效的语言限制吗?
因为这只是语言的定义方式 。
一个方法可以使用
return
语句来将控制权返回给调用者。 在返回void
的方法中,return
语句不能指定expression式。 在返回非void
的方法中,return
语句必须包含一个计算返回值的expression式。
这是一个任意的决定(大概是为了与ANSI C及其后代兼容),其他语言做不同的事情。
例如,在Python中,所有函数都会返回一个值。 如果你执行一个没有值的return
语句,或者让控件到达函数的末尾,那么就像你写了return None
。
相比之下,Pascal将function
的术语限制为具有返回值的子程序; 如果你不想返回任何东西,你可以使用一个procedure
。
void
是信息的缺失; 返回它没有任何意义。 这不是一种types*,它不像其他一些语言那样是一种价值。 不,这不是一个限制。
*好,就像@Lucas指出的那样。 这是一个信息types; 它实际上并不代表通常意义上的types。 你不能有一个。
你的问题是关于void
types和unit
types (在F#等函数式语言中最常见的)之间的区别。
基本上, void
不是一个真正的types。 虽然有System.Void
为reflection目的,你不能使用void
在大多数地方,你可以使用一个真正的types:你不能有一个void
types的variables,你不能用generics(即使是能写Func<void>
有时候会非常有用)。
另一方面,F#中的unit
是一个实数types:它有一个(单个)值(称为()
),可以写成相当于Func<void>
(写unit -> unit
,其中第一个unit
表示“no参数“,类似于在C中的参数列表中写入void
),并且可以具有unit
types的variables。 例如:
let unitTest (f : unit -> unit) = let nothing : unit = f() ()
最后一行实际上表明,在F#中,你有时必须明确地返回unit
。
这归结于语言devise者的select。
从types的angular度来看,void没有可枚举的值,所以返回“void”types的值是没有意义的。 void是缺lesstypes或评估上下文。
你不能在C#或Java中实例化或返回“void”。
如果你能这样做,那么你也应该能够说:
void i; i = (what would go here?) return i;
以上没有任何意义,但相当于你的build议。
最后,提出可以用返回语句来传播无效返回上下文只是一个语法糖的问题,这个问题归结于语言devise者的select。
C#语言规范http://msdn.microsoft.com/en-us/library/aa691305(v=vs.71).aspx(7.1节)说
没有。 当expression式是一个返回types为void的方法的调用时,会发生这种情况。 被分类为“无”的expression式仅在语句expression式的情况下有效(见第8.6节)。
另一方面,C ++devise者实际上select只允许你提出的构造,但是它特别适用于模板中的语法一致性。 在C ++中,模板函数的返回types可以是模板参数。 (Stroustrop C ++编程语言,第148页)如果没有它,将会出现所有types都会编译的常见情况,而不是voidtypes的嵌套函数调用。因此,以下是有效的C ++:
void B() { return; } void A() { return B(); // legal C++ - doesn't yield a value } // But even in C++ the next line is illegal int i = A();
所以语句expression式“return B();” 其中B是无效函数只是“B(); return”的快捷方式。 而实际上并没有产生价值 ,因为没有这样的东西作为空值。
根据语言规范,这是不允许的。 从ECMA-334(重点矿)的15.9.4开始:
具有expression式的return语句只能用于计算值的函数成员,即具有非void返回types的方法 ,属性或索引器的get访问器或用户定义的运算符。
我有一个合法的原因猜测。
当编译器看到一个expression式时,它会尝试将它与已知expression式列表中的内容进行匹配。 你可以说有两种以return
开头的语句:
-
return expr
其中,expr
是一个可分配给包含方法的声明返回types的expression式 - 没有任何其他的
return
这些是完全不同的陈述,即使它们看起来相似。 但是在某些情况下, 可以编译到另一个(就像foreach
编译到一些东西一样)。 所以,你可以添加一个规则,说, return expr
编译为任何expr; return;
expr; return;
编译为,只要expr
被确定为没有返回types(即void
)。
但是,那么C#编译器的实现者将不得不允许所有expression式没有返回types,通常只有语句被允许没有返回types。 如果他们这样做,那么他们将不得不手动禁止在任何需要实际types的地方使用任何types的expression式。 例如,在充当函数调用MyMethod(1, 2, SomethingVoid())
参数的expression式中,编译器还需要检查这些expression式中的任何一个是否不返回types。 对于将来添加到C#中的每一种新的expression式,都必须添加相同的检查。
以上是可能的,但除了允许抽象语法树中的非语句expression式(在编译过程中生成)没有返回types之外,没有任何理由会发生这种情况,只是为了允许一个小的语法结构 – 而且有一种替代方法不再(按键式)input并可能更清晰地阅读。
最后,这听起来不值得。
你真正的问题标题似乎并没有被答案覆盖,虽然他们可能正在得到正确的东西。 你是问题标题
为什么C#不支持返回一个void返回types的方法
其实C#确实允许这个,只是不是你想要的格式。 使用void
关键字作为其他人的答案意味着该方法不返回任何内容。 如果你想返回一个方法,那什么都不返回,那么你想要做这样的事情:
public Action MethodExample() { return () => { Console.WriteLine("Hello World!"); }; }
然后一个简单的电话会给你这个动作:
var action = MethodExample(); action(); // prints Hello World
虚空是空的。 C#语言中的void关键字指示方法不返回任何内容。 当一个void方法被调用时,它没有结果,也没有variables可以被分配。
看到这个解释
纠正我,如果我错了,但我认为它是因为:
public void MethodA() { return; } public void MethodB() { return MethodA(); }
会是一样的(这是合法的):
public void MethodA() { } public void MethodB() { MethodA(); }
并且:
public void MethodMeh() { if (expression) { MethodA(); }else{ // do more stuff } }