PhillyD
PhillyD

Reputation: 174

System.NullReferenceException when using null coalescing operator

I have run into an error that I can not seem to fix. After doing some research on Stack Overflow it seemed as though the null coalescing operator would be the solution to my problem, but it has not helped. Here is the code that gives the error:

List<OperationsReviewLevelResult> results = new List<OperationsReviewLevelResult>();
foreach (var approval in OperationsReviewers.ApprovalItems)
{
     var result = new OperationsReviewLevelResult();
     result.ApproverName = approval.Results.FirstOrDefault().Name ?? "";
     result.ReviewLevel = approval.Name;
     result.Comment = approval.Results.FirstOrDefault().Comments ?? "";
     results.Add(result);
}

When I run this code, I am getting:

Exception Details: System.NullReferenceException: Object reference not set to an instance of an object.

Coming from the line result.ApproverName = approval.Results.FirstOrDefault().Name ?? "";. I added the null coalescing operator to check for null values, but this is not fixing my problem. The error is because there is no Results in approval so I assumed the FirstOrDefault linq method would return the default value, and when it realizes the default value has a null value for Name, it would use the null coalescing operator to return the "" empty string on the right side of the operator.

Please let me know if I am missing something as I can not seem to understand why I am getting this error even when adding the null coalescing operator.

Edit: As suggested in a comment, looking at this post helped me learn more into why I received this error. Although the questions are a bit different, I highly recommend reading the answer for getting a full understanding of my problem.

Upvotes: 1

Views: 1558

Answers (2)

Kit
Kit

Reputation: 21709

After each of your .FirstOrDefault() calls you need to add the ?. operator. Here's a full solution:

List<OperationsReviewLevelResult> results = new List<OperationsReviewLevelResult>();
foreach (var approval in OperationsReviewers.ApprovalItems)
{
     var result = new OperationsReviewLevelResult();
     result.ApproverName = approval.Results.FirstOrDefault()?.Name ?? "";
     result.ReviewLevel = approval.Name;
     result.Comment = approval.Results.FirstOrDefault()?.Comments ?? "";
     results.Add(result);
}

If it's possible other parts of the results could be null, you can go the full paranoid route

List<OperationsReviewLevelResult> results = new List<OperationsReviewLevelResult>();
foreach (var approval in OperationsReviewers.ApprovalItems)
{
     var result = new OperationsReviewLevelResult();
     result.ApproverName = approval?.Results?.FirstOrDefault()?.Name ?? "";
     result.ReviewLevel = approval?.Name;
     result.Comment = approval?.Results?.FirstOrDefault()?.Comments ?? "";
     results.Add(result);
}

And paranoid and LINQ-ified:

var results = OperationsReviewers.ApprovalItems
    .Select(approval => new OperationsReviewLevelResult
    {
        ApproverName = approval?.Results?.FirstOrDefault()?.Name ?? "",
        ReviewLevel = approval?.Name,
        Comment = approval?.Results?.FirstOrDefault()?.Comments ?? ""
    }
    .ToList();

Upvotes: 7

Dmitrii Bychenko
Dmitrii Bychenko

Reputation: 186698

The most probable cause is that FirstOrDefault() returns null (as a default value) and thus FirstOrDefault().Name throws exception. You can try null propagation with help of ?.

   foreach (var approval in OperationsReviewers.ApprovalItems)
     results.Add(new OperationsReviewLevelResult() {
       ApproverName = approval.Results.FirstOrDefault()?.Name ?? "",
       ReviewLevel  = approval.Name,
       Comment      = approval.Results.FirstOrDefault()?.Comments ?? "",
     });

So if approval.Results is empty and thus FirstOrDefault() returns null then FirstOrDefault()?.Name returns null which is finally turns into ""

Upvotes: 7

Related Questions