我有一个简单的LINQ表达式,如:
newDocs = (from doc in allDocs
where GetDocument(doc.Key) != null
select doc).ToList();
问题是,GetDocument()可能会抛出异常。如何忽略GetDocument(doc.Key)== null或抛出异常的所有doc元素?
旧学校的相同代码如下:
foreach (var doc in allDocs)
{
try
{
if (GetDocument(doc.Key) != null) newDocs.Add(doc);
}
catch (Exception)
{
//Do nothing...
}
}
答案 0 :(得分:18)
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();
答案 1 :(得分:12)
您可以将整个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();
这将使您的查询简洁易读。
答案 2 :(得分:12)
可以编写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 :(得分:3)
您是否尝试过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();
答案 4 :(得分:1)
编写自己的方法。 MyGetDocument( )
将处理异常并从LINQ调用它。
newDocs = (from doc in allDocs
where MyGetDocument(doc.Key) != null
select doc).ToList();