我正在使用......
tmpLst = (from e in App.lstAllChilds where e.Id == Id select e).ToList();
其中lstAllChilds
是列表,其中也包含一些损坏的数据。
所以现在我想在这个查询中处理Try-Catch块 请帮忙。
答案 0 :(得分:9)
如果您只是想忽略“坏元素”,那么:
App.lstAllChilds.SkipExceptions().Where( e => e.Id == Id).ToList();
扩展方法:
public static class Extensions
{
public static IEnumerable<T> SkipExceptions<T>(this IEnumerable<T> values)
{
using (var enumerator = values.GetEnumerator())
{
bool next = true;
while (next)
{
try
{
next = enumerator.MoveNext();
}
catch
{
continue;
}
if (next) yield return enumerator.Current;
}
}
}
}
答案 1 :(得分:4)
这是您可以做的最简单的更改,只需排除null或引发异常的项目。
tmpLst = App.lstAllChilds.Where(e =>
{
try
{
return e != null && e.Id == Id;
}
catch
{
return false;
}
}).ToList();
但在我看来,你可能应该调查并解决潜在的问题。这似乎不是预期异常的情况。
答案 2 :(得分:3)
所以,这就是事情。有语言集成查询(Linq),然后产生枚举(a.k.a.迭代器)。
Linq允许您定义一个表达式树,该表达式树稍后由可能是或不是C#的东西执行(例如,表达式可以转换为SQL查询)。如果你正在编写linq,你的查询提供程序(表达式转换的东西)很可能不支持异常处理(更不用说你正在做什么抛出异常)。
另一方面,对象(或“linq to objects”)最终只能在C#中执行,因此您可以对异常处理进行粗略的处理。
例如w / linq到对象,你可以这样做:
var myList = new[] { "1", "2", "BARF", "3" };
var sum = myList.Select(str => {
try {
return Int32.Parse(str);
} catch {
return 0;
}
}).Aggregate((x, y) => x + y);
如果您确实在对象中执行linq,并且您只想跳过源IEnumerable引发异常的元素,请查看Vladimir Gondarev的答案。
然而,要理解的重要一点是,我们刚刚传递给Select调用的匿名函数不是Expression(未编译的表达式树),它是一个Func(指向编译的委托) c#code),这意味着它将在.Net进程中运行,即使我们用linq替换myList到实体表(或其他一些linq提供程序)。原因是C#表达式语法不支持块,也不支持try-catch。不出所料,鉴于此,SQL样式的Linq语句(来自xxx select yyy)也不支持try-catch块。
但是,仅仅因为C#表达式语法不支持它并不意味着你不能这样做。但是,要清楚,我不建议这样做,因为我高度怀疑是否存在支持它的QueryProvider(除了linq到对象提供者)。好奇的是,你将如何创建一个包含try-catch块的lambda表达式。
var parseMethod = typeof(Int32).GetMethod("Parse", new[] { typeof(String) });
var param = Expression.Parameter(typeof(String));
var selectExp =
Expression.Lambda<Func<String, Int32>>(
Expression.TryCatch(
Expression.Call(parseMethod, param),
Expression.Catch(typeof(Exception), Expression.Constant(0))
),
param
);
var sum = myList.Select(selectExp).Aggregate((x, y) => x + y);
因此,当有人实现由支持异常处理的商店支持的QueryProvider时,您可以使用它。
答案 3 :(得分:2)
这取决于你想要达到的目的:
返回“破损”项目以外的列表。
您可以尝试使用Where
子句检查并过滤掉它们:
App.lstAllChilds.Where(x => IsValidNode(x, Id)).ToList();
显然你需要实现IsValidNode
,它应检查null
,如果它可以抛出InvalidObjectException
(不确定你是否可以轻松检测到它,但你可以随时将它包裹起来try-catch块)和Id
相等。像那样:
private bool IsValidNode(Child c, int id)
{
if (x == null) return false;
try {
return c.Id == id;
}
catch (InvalidObjectException)
{
}
return false;
}
如果有任何损坏的项目,请返回一个空列表。