NET问答:在 Linq 查询中可以处理异常吗?

咨询区

  • 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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值