咨询区
Jader Dias:
先上例子:
myEnumerable.Select(a => ThisMethodMayThrowExceptions(a));
如何让上面的 Linq查询
即使在抛出异常的情况下也能完整的执行,就像那种带有默认值的 try...catch
一样,当异常抛出时总会执行 catch 后再把它救回来。
回答区
Stefan Steinegger:
myEnumerable.Select(a => {try{return ThisMethodMayThrowExceptions(a));}catch(Exception){return defaultValue;}});
本质上来说,上面这段代码大体上能解决你的问题,但有一些坏味道。
LeBaptiste:
我自己写了一些 扩展方法
可以捕获 IEnumerable<T>
中每一个迭代项的异常。
用法
public void Test()
{List<string> completedProcesses = initialEnumerable.SelectTry(x => RiskyOperation(x)).OnCaughtException(exception => { _logger.Error(exception); return null; }).Where(x => x != null) // filter the ones which failed.ToList();
}
扩展方法
public static class OnCaughtExceptionExtension
{public static IEnumerable<SelectTryResult<TSource, TResult>> SelectTry<TSource, TResult>(this IEnumerable<TSource> enumerable, Func<TSource, TResult> selector){foreach (TSource element in enumerable){SelectTryResult<TSource, TResult> returnedValue;try{returnedValue = new SelectTryResult<TSource, TResult>(element, selector(element), null);}catch (Exception ex){returnedValue = new SelectTryResult<TSource, TResult>(element, default(TResult), ex);}yield return returnedValue;}}public static IEnumerable<TResult> OnCaughtException<TSource, TResult>(this IEnumerable<SelectTryResult<TSource, TResult>> enumerable, Func<Exception, TResult> exceptionHandler){return enumerable.Select(x => x.CaughtException == null ? x.Result : exceptionHandler(x.CaughtException));}public static IEnumerable<TResult> OnCaughtException<TSource, TResult>(this IEnumerable<SelectTryResult<TSource, TResult>> enumerable, Func<TSource, Exception, TResult> exceptionHandler){return enumerable.Select(x => x.CaughtException == null ? x.Result : exceptionHandler(x.Source, x.CaughtException));}public class SelectTryResult<TSource,TResult>{internal SelectTryResult(TSource source, TResult result, Exception exception){Source = source;Result = result;CaughtException = exception;}public TSource Source { get; private set; }public TResult Result { get; private set; }public Exception CaughtException { get; private set; }}
}
如果还想完美一点,可以再实现一个 SkipOnException
, 接收可以忽略的异常。
点评区
回答区的两个答案,第一种方法简单粗暴,但各位也能体会出这种写法的生硬之处,第二种写法就比较????????了,让我想起了强大的 Polly (基于.NET的弹性及瞬态故障处理库),各种眼花缭乱的玩法,大家有兴趣可以看一看: https://github.com/App-vNext/Polly
原文链接:https://stackoverflow.com/questions/1294251/is-it-possible-to-handle-exceptions-within-linq-queries