为什么异常没有被关闭?

时间:2016-02-11 16:15:28

标签: c# exception lambda

以下是代码示例:

Apache Tomcat 7

现在,如果 public IList<LogEntry> ReadLogs(Guid id, string name) { var logs = this.RetrieveLogs(id, name); if (logs != null) { foreach (LogEvent logEvent in logs) { // bla, bla, bla } } return logEntries; } private IEnumerable<LogEvent> RetrieveLogs(Guid id, string name) { try { FilterCriteria filterCriteria = CreateFilterCriteria(); return (from log in this.loggingProvider.ReadLogs(filterCriteria, 1) where log.ParticipantObjects[0].ParticipantObjectId == id.ToString() && log.LogEventParameters[0].Value == name orderby log.Timestamp.ToLocalTime() descending select log).AsEnumerable(); } catch (Exception ex) { this.tracer.Write(Category.Error, ex, "Error"); return null; } } 方法中存在异常,则会捕获并跟踪它。但是,例如,如果没有loggingProvider.ReadLogs(),则此异常不会被捕获并在此处跟踪。它似乎与lambda表达式和闭包有关。

解释是什么?

3 个答案:

答案 0 :(得分:15)

之前我已经说过了,我无疑会再说一遍:了解查询最重要的一点是查询是一个问题,而不是问题的答案

您构建的查询对象不仅仅通过构建它来执行。你正在构建这个问题。在您执行查询之前,问题实际上并没有被要求回答。并且执行在try块之外。

答案 1 :(得分:5)

loggingProvider.ReadLogsRetrieveLogs内执行。但是只有当你在外部this.ReadLogs迭代它们时才会执行所有其他lambda。

因此,在您的upper方法中抛出异常,因此无法在RetrieveLogs内捕获。

要避免这种情况,请将AsEnumerable更改为ToList()ToArray(),以确保在返回之前实际执行查询。

答案 2 :(得分:3)

LINQ查询的IEnumerable结果仅在枚举时进行评估。

为了将Exception抛出到您期望的位置,您需要使用IEnumerable之类的相关扩展方法枚举LINQ查询结果ToList()

作为旁注(借用Rene Vogt),您可以通过编写LINQ来避免抛出Exception,如下所示:

return this.loggingProvider.ReadLogs(filterCriteria, 1).Where(log => 
    log.ParticipantObjects.FirstOrDefault() != null &&
    log.ParticipantObjects[0].ParticipantObjectId == id.ToString() &&
    log.LogEventParameters[0].Value == name).OrderBy(log => 
    log.Timestamp.ToLocalTime()).ToList();