提问人:Rachel 提问时间:8/25/2023 更新时间:8/25/2023 访问量:40
在 lambda 中引发的异常未被 catch 块捕获 [duplicate]
Exception thrown within lambda not caught by catch block [duplicate]
问:
我已经看到了一些关于 lambda 和异常的问题,但我仍然不明白我在代码中看到的行为。
class MyObj
{
public object Prop1 { get; set; }
}
public void Get()
{
try
{
IEnumerable<MyObj> collection = new List<MyObj>() { new MyObj() };
collection = collection.Where(x =>
{
return x.Prop1.ToString() == "some value";
});
}
catch (Exception ex)
{
throw new UriFormatException($"Invalid filter. Error details: {ex.Message}");
}
}
由于为 null,因此会引发“对象引用未设置为对象的实例”异常。但是,代码不会进入块。如果我添加更多尝试在块中使用的代码,则当 lambda 中遇到异常时,将输入该块。例如Prop1
catch
collection
try
catch
foreach (var c in collection)
{
Console.WriteLine(c);
}
如果在执行 lambda 时出现任何异常,我希望输入 catch 块。我尝试编写一个命名函数以从 lambda 调用,这也不起作用。我错过了什么?
答:
1赞
StriplingWarrior
8/25/2023
#1
LINQ 运算符喜欢使用称为“延迟执行”的东西。这意味着,当您调用它们时,它们实际上并没有执行您提供给它们的 lambda:它们只是返回一个跟踪 lambda 和源的新查询。然后,当您尝试执行该查询时,它将开始评估 lambda。Where
这可能是有益的,因为如果您最终在查询末尾放置了类似 a 或 a 的内容,则可以避免对集合中的每个项目运行委托。但由于各种原因,它可能会有问题:如果同一个查询被多次执行,它将重复大量工作;如果 Lambda 中捕获的值在执行之前发生更改,则可以有意义地更改查询的行为。.First()
.Take(10)
因此,如果你想捕获查询委托中抛出的异常,你要么需要在 foreach 循环周围放置一个 try/catch,要么在其中放置类似 a 的东西来强制立即执行。.ToList()
try
{
var collection = new List<MyObj>() { new MyObj() }
.Where(x =>x.Prop1.ToString() == "some value")
.ToList();
}
catch (Exception ex)
{
throw new UriFormatException($"Invalid filter. Error details: {ex.Message}");
}
评论