LINQ表达式中的异常处理

Roc*_*ark 16 c# linq-to-objects

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

newDocs = (from doc in allDocs
       where GetDocument(doc.Key) != null
       select doc).ToList();
Run Code Online (Sandbox Code Playgroud)

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

旧学校的相同代码如下:

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

Mar*_*tos 19

allDocs.Where(doc => {
    try {
        return GetDocument(doc.Key) != null;
    } catch {
        return false;
    }
}).ToList();
Run Code Online (Sandbox Code Playgroud)

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

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


kat*_*yte 14

可以编写linq扩展名以跳过导致异常的所有元素.请参阅此stackoverflow帖子

 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;
                }
            }
        }
    }
Run Code Online (Sandbox Code Playgroud)

例:

ienumerable.Select(e => e.something).CatchExceptions().ToArray()

ienumerable.Select(e => e.something).CatchExceptions((ex) => Logger.Log(ex, "something failed")).ToArray()
Run Code Online (Sandbox Code Playgroud)

发布此处以防万一其他人首先找到此答案.


Unm*_*kar 12

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

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

然后在您的查询中使用此功能 -

newDocs = (from doc in allDocs
       where TryGetDocument(doc.Key) != null
       select doc).ToList();
Run Code Online (Sandbox Code Playgroud)

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