使用类似这样的事件将异常从您调用的实际方法调用中断开。我认为最好为此使用Exception monad。
你的类应该是这样的:那么
public class StatisticalCalculations
{
public Exceptional<double> GetStandardDeviation(IEnumerable<double> values)
{
try
{
double standardDeviation = double.NaN;
//Perform calculation
return standardDeviation.ToExceptional();
}
catch (Exception ex)
{
return new Exceptional<double>(ex);
}
}
}
您的通话功能,可解压Exceptional<double>
,看它是否有一个值,或者如果它得到了一个错误。
你需要支持这样做的类:
public class Exceptional<T>
{
public bool HasException { get; private set; }
public Exception Exception { get; private set; }
public T Value { get; private set; }
public Exceptional(T value)
{
HasException = false;
Value = value;
}
public Exceptional(Exception exception)
{
HasException = true;
Exception = exception;
}
public Exceptional(Func<T> func)
{
try
{
this.Value = func();
this.HasException = false;
}
catch (Exception exc)
{
this.Exception = exc;
this.HasException = true;
}
}
public override string ToString()
{
return this.HasException
? Exception.GetType().Name
: (this.Value != null
? this.Value.ToString()
: "null");
}
}
public static class ExceptionalEx
{
public static Exceptional<T> ToExceptional<T>(this T value)
{
return new Exceptional<T>(value);
}
public static Exceptional<T> ToExceptional<T>(this Func<T> func)
{
return new Exceptional<T>(func);
}
public static Exceptional<U> SelectMany<T, U>(this Exceptional<T> value, Func<T, Exceptional<U>> k)
{
return (value.HasException)
? new Exceptional<U>(value.Exception)
: k(value.Value);
}
public static Exceptional<V> SelectMany<T, U, V>(this Exceptional<T> value, Func<T, Exceptional<U>> k, Func<T, U, V> m)
{
return value.SelectMany(t => k(t).SelectMany(u => new Exceptional<V>(() => m(t, u))));
}
}
_“这是一个不好的做法......” _ - 舆论彻底的问题,因而不适合堆栈溢出。也就是说,我没有看到好处;视图模型本身很容易实现某种集中式异常报告,并且可以以更合适的方式来实现。你的例子捕获_all_异常,这是一个绝对不好的主意。但是与此同时,只有调用者真正知道它能够合理地处理什么,以及应该怎样强制该过程终止。 –
我不同意彼得。有一个好处。将异常消息转储到记录器并保存到文件中没有区别;或者将一个异常添加到可枚举对象中。使用你的代码没有问题。真正的问题是找到例外的根源。事件是异步的,所以只要将错误消息添加到记录器中就不会指示发生错误的地方。因此添加堆栈跟踪将提供更多信息。 – jdweng
而不是订阅一个事件,为什么你不能只处理来自调用代码的异常?这可能是一个应用程序范围的包装器(ASP.NET MVC是如何工作的)或包装调用的调用者特定逻辑。 – AndrewP