Why didn’t the exception go to close?

Here is a sample code:

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; } } 

Now, if there was an exception in the loggingProvider.ReadLogs() method, it will be caught and traced. But if, for example, there is no ParticipantObjects[0] , this exception will not be caught and traced here. This seems to have something to do with lambda expressions and closures.

What is the explanation?

+5
source share
3 answers

loggingProvider.ReadLogs runs inside RetrieveLogs . But all other lambdas are executed only when you this.ReadLogs over them in the external this.ReadLogs .

Thus, the exception is thrown into your top method and therefore cannot be caught inside RetrieveLogs .

To avoid this, change AsEnumerable to ToList() or ToArray() to ensure that the request is actually executed before returning.

+5
source

I have already spoken about this, and I will no doubt repeat it: The most important thing to know about the request is the question, not the answer to the question .

The request object that you created is not executed only by creating it. You are building a question. The question is not asked or answered until you complete the request. And the execution is done outside of the try block.

+15
source

An IEnumerable LINQ query result is evaluated only when enumerated.

In order for the Exception be thrown where you expect it, you need to list the result of the LINQ IEnumerable query using one of the appropriate extension methods, for example ToList() .

As a side note (borrowing from Rene Vogt), you can prevent the Exception being thrown by writing LINK as follows:

 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(); 
+3
source

Source: https://habr.com/ru/post/1242794/


All Articles