Catch块永远不会在LINQ语句中触发

时间:2016-11-02 22:05:29

标签: c# linq

我在Linq语句中反序列化了一些数据:

var scheduledData = results
   .Where(o => o.Result.IsValid)
   .SelectMany(o => JsonConvert.DeserializeObject<List<CalendarJob>>(o.Result.Response))
   .ToList();

这是一个错误。我从未在调试器中看到此错误。返回的网页列出了显示此错误的500错误。所以我添加了一些处理:

var scheduledData = results
   .Where(o => o.Result.IsValid)
   .SelectMany(o => {
      try {
         return JsonConvert.DeserializeObject<List<CalendarJob>>(o.Result.Response);
      }
      catch {
         return new List<CalendarJob>();
      }
   })
   .ToList();

是的,这真的很难看。我这样做,所以我可以在catch块上设置一个断点,这样我就可以检查一些值了。这不是我留下的代码! :)

我在return块内的try语句以及catch块中放置了断点。然后我执行代码。 try语句命中并执行消失。 catch块永远不会触发,也不会在我的方法中执行任何其他代码。

catch中是否允许此linq阻止?我当然这么认为?

是的,我处于调试模式。是的,我已经清理并重建了。我的try块上的断点确实命中了。我可以检查即将反序列化的字符串的值,并且值不正确。它是""。我的意思并不是string.Empty,我特别指的是字符串包含两个字节,两者都是双引号字符。我从中获取数据的服务没有返回好的数据。但我的catch块永远不会发射。

还有一点需要注意。我将整个事件放入try...catch块中,并且该块 命中。只有LINQ内的那个没有。

2 个答案:

答案 0 :(得分:2)

是的 - 这将按您认为的方式运作。

唯一不起作用的时间是你无法捕捉到的例外情况,例如StackOverflowException

为了证明这一点,只需在Visual Studio或Linqpad中执行以下代码,然后观察断点被击中两次。

var list = new List<string>
{
    "a",
    "b"
};

list.Select(i =>
{
    try
    {
        return int.Parse(i);
    }
    catch
    {
        return 0; // Put a breakpoint here.
    }
}).ToList();

答案 1 :(得分:0)

我找到了原因。内部JsonConvert不会使用无效的Json抛出错误。相反,它返回null。因此try...catch周围的JsonConvert区块没有做任何事情,因为没有什么可以抓住的。接下来,SelectMany期待一个List<>项目,并尝试枚举它以从中选择元素。因为它收到了null,所以错误被抛出,而不是在Json转换中。这就是外部try...catch获取错误但上面的OP中没有错误的原因。

我接受了RB的答案,因为他回答了我原来的问题。这只是对任何未来发现者的解释。