当不是所有代码路径 return 时,C# 编译器不会报错
C# compiler doesn't complain when not all code paths return
我有一个 returning 在 using
块中的函数:
int f() {
using (...) {
...
return someVar;
}
}
我刚刚注意到这一点,并将 return
移到了 using
块之外,移到了最外层的函数范围,因为我觉得那是 return
应该在的地方。
但我很困惑为什么编译器没有抱怨并非所有代码路径都是 returning。是否仅仅是因为如果它无法初始化资源,我们就会崩溃,所以这无关紧要?
举个例子:
class MainClass {
public static void Main (string[] args) {
f();
}
public static int f() {
using(A a = new A()) {
return 1;
}
}
}
class A : IDisposable{
public void Dispose() { }
}
编译器不关心我们在using
中只return。但是,我认为 using
语句基本上是 try/catch
的语法糖
如果我们替换
using(A a = new A()) {
return 1;
}
与
A a = new A();;
try {
return 1;
}
catch (Exception e) { }
finally {
if (a != null) {
((IDisposable) a).Dispose();
}
}
确实编译器抱怨:
error CS0161: `MainClass.f()': not all code paths return a value
为什么在另一种情况下它不抱怨?
仅仅是我上面说的吗? 如果它无法初始化资源,我们就会崩溃,所以编译器认为这无关紧要。
基本上,是的。 using
语句会将其异常抛出堆栈。捕获异常并使用不 return 的 finally 块意味着该方法既不会抛出异常也不会 return.
编译器也不会抱怨像下面这样的方法
public int SuperCool(){
throw new NotImplementedException("bummer");
}
为了扩展一点,因为我错过了一个 catch 块最初不存在的编辑:
让 catch
块 "eats" 异常导致它不能进一步向上移动堆栈,编译器注意到没有路径 return 是一个值或一个异常.
实际上是:
using(var objectName = <init-expression>) {
//...
}
大致等同于:
objectName = <init-expression>;
try {
//...
} finally {
objectName.Dispose();
}
所以是一个try
-finally
-block:如果执行过程中出现问题,异常会被抛出方法外(主要是在finally
部分之后已完成)。
A try
-finally
但是不会创建替代代码路径:如果 try
-部分 return 有问题或抛出错误,它将首先执行 finally
部分,然后抛出异常或 return 应该 returned.
我有一个 returning 在 using
块中的函数:
int f() {
using (...) {
...
return someVar;
}
}
我刚刚注意到这一点,并将 return
移到了 using
块之外,移到了最外层的函数范围,因为我觉得那是 return
应该在的地方。
但我很困惑为什么编译器没有抱怨并非所有代码路径都是 returning。是否仅仅是因为如果它无法初始化资源,我们就会崩溃,所以这无关紧要?
举个例子:
class MainClass {
public static void Main (string[] args) {
f();
}
public static int f() {
using(A a = new A()) {
return 1;
}
}
}
class A : IDisposable{
public void Dispose() { }
}
编译器不关心我们在using
中只return。但是,我认为 using
语句基本上是 try/catch
如果我们替换
using(A a = new A()) {
return 1;
}
与
A a = new A();;
try {
return 1;
}
catch (Exception e) { }
finally {
if (a != null) {
((IDisposable) a).Dispose();
}
}
确实编译器抱怨:
error CS0161: `MainClass.f()': not all code paths return a value
为什么在另一种情况下它不抱怨?
仅仅是我上面说的吗? 如果它无法初始化资源,我们就会崩溃,所以编译器认为这无关紧要。
基本上,是的。 using
语句会将其异常抛出堆栈。捕获异常并使用不 return 的 finally 块意味着该方法既不会抛出异常也不会 return.
编译器也不会抱怨像下面这样的方法
public int SuperCool(){
throw new NotImplementedException("bummer");
}
为了扩展一点,因为我错过了一个 catch 块最初不存在的编辑:
让 catch
块 "eats" 异常导致它不能进一步向上移动堆栈,编译器注意到没有路径 return 是一个值或一个异常.
实际上是:
using(var objectName = <init-expression>) {
//...
}
大致等同于:
objectName = <init-expression>;
try {
//...
} finally {
objectName.Dispose();
}
所以是一个try
-finally
-block:如果执行过程中出现问题,异常会被抛出方法外(主要是在finally
部分之后已完成)。
A try
-finally
但是不会创建替代代码路径:如果 try
-部分 return 有问题或抛出错误,它将首先执行 finally
部分,然后抛出异常或 return 应该 returned.