Обработка исключений в выражении LINQ
У меня есть простое выражение LINQ, например:
newDocs = (from doc in allDocs
where GetDocument(doc.Key) != null
select doc).ToList();
Проблема заключается в том, что GetDocument() может генерировать исключение. Как я могу игнорировать все doc-элементы, где GetDocument (doc.Key) == null или генерирует исключение?
Тот же код в старой школе выглядит следующим образом:
foreach (var doc in allDocs)
{
try
{
if (GetDocument(doc.Key) != null) newDocs.Add(doc);
}
catch (Exception)
{
//Do nothing...
}
}
Ответы
Ответ 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
Вы можете переместить весь блок 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();
Это упростит ваш запрос и будет легко читаться.
Ответ 3
Расширение linq можно записать, чтобы пропустить все элементы, которые вызывают исключение. fooobar.com/questions/257645/...
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()
разместив это здесь, если кто-то еще найдет этот ответ первым.
Ответ 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();