我想编写一个扩展方法来更自然地抛出新的异常(通常很好奇关键字' throw'实际上是如何工作的)。我想知道为什么以下代码不起作用:
public static bool Foo() {
bool bar = false;
try {
var zero = 0;
// force exception
var result = 1 / zero;
return bar;
} catch (Exception ex) {
ex.ThrowNew("Failed to return Bar");
// instead of throw new Exception("Failed to return Bar", ex);
}
}
ex.ThrowNew方法是以下扩展方法:
public static void ThrowNew(this Exception ex, string message) {
throw new Exception(message, ex);
}
显然,当异常抛出在catch中时,Foo()方法正常工作,而不是扩展方法,因为它在抛出时停止执行该方法。
修改 应用程序不会编译,因为该方法并非所有代码路径都返回有效结果(因为异常将在Extension方法中抛出,而不是原始方法)
答案 0 :(得分:1)
我相信this是您正在寻找的。问题是,编译器需要静态验证您是否从每个代码路径返回一些内容。由于您使用的是此扩展程序,因此无法推断出这一事实,并且您收到了错误消息:
CS0161' Foo()':并非所有代码路径都返回值
答案 1 :(得分:1)
投掷Exception
课程是不良做法以及在没有通过Exception
重新投掷的情况下抓住throw;
(请注意语法):
// Whatever happened (e.g. CPU starts emittinig green smoke)
} catch (Exception ex) {
// throw Exception instance which means nothing more than "Something went wrong"
ex.ThrowNew("Failed to return Bar");
}
首先,让我们修改初始代码:
try {
...
}
// We do know the cause, that's why we have a right to catch and re-throw
catch (DivideByZeroException e) {
// Be specific, do not throw Exception! Since MyBarException can be caought in "catch"
throw new MyBarException("Failed to return Bar because...", e);
}
我怀疑你是否想要任何扩展方法,但是,如果你坚持要把它放在像
这样的东西上// Doesn't compile; to show the idea only
public static void ThrowNew<T>(this Exception ex, string message)
where T: Exception {
if (null == ex)
return; // or throw ArgumentNullException("ex");
throw new T(message, ex); // <- this line fails to compile
}
上面的代码存在new T
的问题(.Net无法确定任意T
是否具有构造函数
必填),所以你必须为
public static void ThrowNew<T>(this Exception ex, string message)
where T: Exception {
if (null == ex)
return; // or throw ArgumentNullException("ex");
throw (Exception) (typeof(T)
.GetConstructor(new Type[] { typeof(String), typeof(Exception)})
.Invoke(message, ex));
}
所以你可以把
catch (DivideByZeroException e) {
e.ThrowNew<MyBarException>("Failed to return Bar because...");
// Ugly little thing:
// "if (null == ex)" in the extension method doesn't throw any exception
return false;
}
,恕我直言,不太可读,因此不应使用