为什么C#不允许我将void方法作为return语句的一部分调用?

时间:2014-07-10 00:15:55

标签: c# void

我很好奇是否有正当理由说明当调用方法的返回类型也无效时,为什么C#不支持将void方法作为return语句的一部分调用。

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#如何处理void,这是一种语言限制吗?

9 个答案:

答案 0 :(得分:39)

因为它只是the language is defined的方式。

  

方法可以使用return语句将控制权返回给其调用者。   在返回void的方法中,return语句无法指定   表达式。在返回非voidreturn语句的方法中必须   包括一个计算返回值的表达式。

这是一个随意的决定(可能是为了与ANSI C及其他后代兼容),而其他语言则以不同的方式做事。

例如,在Python中,所有函数都返回一个值。如果你执行一个没有值的return语句,或让控件到达函数的末尾,那就像你写的return None一样。

相比之下,Pascal将function的术语限制为具有返回值的子程序;如果您不想返回任何内容,请使用procedure代替。

答案 1 :(得分:28)

void缺少信息;归还它没有任何意义。它不是类型*,与其他语言不同,它不是一个值。不,这不是一个限制。

*好吧,正如@Lucas指出的那样。这是一种信息类型;它实际上并不代表通常意义上的类型。你不能拥有一个。

答案 2 :(得分:7)

您的问题几乎与the void typethe unit type之间的差异有关(最常见于F#等函数式语言)。

基本上,void不是真正的类型。虽然有System.Void用于反射目的,但在大多数可以使用实际类型的地方都不能使用void:您不能拥有void类型的变量,并且可以在泛型中使用它(即使能够写Func<void>有时非常有用)。

另一方面,F#中的unit是一个真实的类型:它有一个(单个)值(称为()),你可以写出等价的Func<void>(书面{ {1}},其中第一个unit -> unit表示“无参数”,类似于在C中的参数列表中编写unit,您可以使用void类型的变量。例如:

unit

最后一行实际显示在F#中,您有时必须显式返回let unitTest (f : unit -> unit) = let nothing : unit = f() ()

答案 3 :(得分:4)

根据语言规范,这是不允许的。从ECMA-334的15.9.4(强调我的):

  

带有表达式的return语句只能在计算值的函数成员中使用   是,具有非void返回类型的方法,属性或索引器的get访问器或用户定义的方法   操作

答案 4 :(得分:4)

归结为语言设计师的选择。

从类型的角度来看,void没有可枚举的值,所以返回“void”类型的值是没有意义的? void是缺少类型或评估上下文。

您无法在C#或Java中实例化或返回“void”。

如果你能这样做,那么你也应该说:

 void i;
 i = (what would go here?)
 return i;

以上没有任何意义,但相当于你的建议。

最后,提出我们可以使用return语句传播void返回上下文只是语法糖的问题,这取决于语言设计者做出的选择。

C#语言规范http://msdn.microsoft.com/en-us/library/aa691305(v=vs.71).aspx (第7.1节)说

  
    

无。当表达式是返回类型为void的方法的调用时,会发生这种情况。分类为空的表达式仅在语句表达式的上下文中有效(第8.6节)。

  

另一方面,C ++设计者实际上选择只允许你提出的构造,但它专门用于模板中的语法一致性。在C ++中,模板函数的返回类型可以是模板参数。 (Stroustrop C ++编程语言第148页)没有它,会有一些常见的情况可以为所有类型编译,但不会为void编译,例如类型为T的嵌套函数调用。因此,以下是有效的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();

所以语句表达式“return B();”其中B是void函数只是“B(); return;”的快捷方式。并且实际上不会产生值,因为没有void值这样的东西。

答案 5 :(得分:2)

我猜这是合理的原因。

当编译器看到表达式时,它会尝试将其与已知表达式列表中的某些内容进行匹配。您可以说有两种语句以return开头:

  1. return expr其中expr是可分配给包含方法的声明返回类型的表达式
  2. return没有其他任何内容
  3. 这些是完全不同的陈述,即使它们看起来相似。但是在某些情况下,一个可以编译到另一个(就像foreach编译为while加上东西一样)。因此,每当return expr被确定为无返回类型(即expr; return;)时,您可以添加一条规则,指出expr编译为void编译的任何内容。 。

    但是,C#编译器的实现者必须允许所有表达式都没有返回类型,而通常只允许语句没有返回类型。如果他们这样做,那么他们将不得不在需要实际类型的地方手动禁止任何类型的表达式。例如,在充当函数调用MyMethod(1, 2, SomethingVoid())的参数的表达式中,编译器还必须检查这些表达式中的任何一个是否不返回类型。对于将来添加到C#的每种新表达式,都必须添加相同的检查。

    以上是可能的,但除了允许抽象语法树中的非语句表达式(在编译期间生成的)没有返回类型之外,它将无缘无故地发生,情况就是这样。只是为了允许一个小的句法结构 - 并且有一个替代品,不再(按键)键入并且可能更清楚地阅读。

    最后,它听起来并不值得。

答案 6 :(得分:2)

您的实际问题标题似乎没有被答案涵盖,尽管他们可能会得到正确的答案。你有问题标题

  

为什么C#不支持返回带有void返回类型的方法

实际上C#确实允许这样做,而不是你尝试的格式。使用void关键字作为其他人已经回答意味着该方法不返回任何内容。如果你想返回一个没有返回任何内容的方法,那么你想做这样的事情:

public Action MethodExample()
{
    return () => { Console.WriteLine("Hello World!"); };
}

然后一个简单的电话会给你这个动作:

var action = MethodExample();
action(); // prints Hello World

答案 7 :(得分:1)

  

void 为空。 C#语言中的void关键字表示a   方法什么都不返回当调用void方法时,它没有   结果,不能分配任何变量。

see this explanation

答案 8 :(得分:-1)

如果我错了,请纠正我,但我认为是因为:

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
    }
}