【问题标题】:Exception handling within a LINQ ExpressionLINQ 表达式中的异常处理
【发布时间】:2010-12-01 08:42:55
【问题描述】:

我有一个简单的 LINQ 表达式,例如:

newDocs = (from doc in allDocs
           where GetDocument(doc.Key) != null
           select doc).ToList();

问题是,GetDocument() 可能会抛出异常。如何忽略 GetDocument(doc.Key) == null 或引发异常的所有文档元素?

旧学校的相同代码看起来像:

foreach (var doc in allDocs)
{
    try
    {
        if (GetDocument(doc.Key) != null) newDocs.Add(doc);
    }
    catch (Exception)
    {
        //Do nothing...
    }
}

【问题讨论】:

标签: c# linq-to-objects


【解决方案1】:
allDocs.Where(doc => {
    try {
        return GetDocument(doc.Key) != null;
    } catch {
        return false;
    }
}).ToList();

我不确定是否可以使用查询理解语法,除非通过一些像这样的巴洛克暴行:

newDocs = (from doc in allDocs
           where ((Predicate<Document>)(doc_ => {
               try {
                   return GetDocument(doc_.Key) != null;
               } catch {
                   return false;
               }
           }))(doc)
           select doc).ToList();

【讨论】:

    【解决方案2】:

    可以编写一个 linq 扩展来跳过所有导致异常的元素。 See this stackoverflow post

     public static IEnumerable<T> CatchExceptions<T> (this IEnumerable<T> src, Action<Exception> action = null) {
            using (var enumerator = src.GetEnumerator()) {
                bool next = true;
    
                while (next) {
                    try {
                        next = enumerator.MoveNext();
                    } catch (Exception ex) {
                        if (action != null) {
                            action(ex);
                        }
                        continue;
                    }
    
                    if (next) {
                        yield return enumerator.Current;
                    }
                }
            }
        }
    

    例子:

    ienumerable.Select(e => e.something).CatchExceptions().ToArray()
    
    ienumerable.Select(e => e.something).CatchExceptions((ex) => Logger.Log(ex, "something failed")).ToArray()
    

    在此处发布,以防其他人先找到此答案。

    【讨论】:

      【解决方案3】:

      您可以将整个try catch 块和GetDocument 调用移动到另一个方法

      Document TryGetDocument(string key)
      {
               try
               {
                  if (GetDocument(doc.Key) != null) 
                    return doc;
               }
               catch (Exception)
               {
                   return null;
               }
           return null;
      }
      

      然后在你的查询中使用这个函数 -

      newDocs = (from doc in allDocs
             where TryGetDocument(doc.Key) != null
             select doc).ToList();
      

      这将使您的查询简洁易读。

      【讨论】:

        【解决方案4】:

        你试过 Expression.TryCatch

        IEnumerable<string> allDocs = new List<string>();
        var newDocs = (from doc in allDocs
                            where Expression.TryCatch(
                                  Expression.Block(GetDocument(doc.key)),
                                  Expression.Catch(typeof(Exception),null)) != null                                 
                                  select doc).ToList();
        

        TryExpression msdn

        【讨论】:

          【解决方案5】:

          编写自己的方法。 MyGetDocument( ) 将处理异常并从 LINQ 调用它。

          newDocs = (from doc in allDocs
                 where MyGetDocument(doc.Key) != null
                 select doc).ToList();
          

          【讨论】:

            猜你喜欢
            • 2021-10-09
            • 1970-01-01
            • 1970-01-01
            • 2017-03-16
            • 2015-08-19
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多