System.NullReferenceException при использовании нулевого оператора объединения - PullRequest
1 голос
/ 29 января 2020

Я столкнулся с ошибкой, которую не могу исправить. После некоторого исследования переполнения стека казалось, что нулевой оператор объединения будет решением моей проблемы, но это не помогло. Вот код, который выдает ошибку:

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

Когда я запускаю этот код, я получаю:

Сведения об исключении: System.NullReferenceException: ссылка на объект не установлена ​​на экземпляр объекта.

Исходя из строки result.ApproverName = approval.Results.FirstOrDefault().Name ?? "";. Я добавил оператор объединения нулей, чтобы проверить наличие нулевых значений, но это не решает мою проблему. Ошибка в том, что в утверждении нет Results, поэтому я предположил, что метод FirstOrDefault linq вернет значение по умолчанию, а когда он поймет, что значение по умолчанию имеет нулевое значение для Name, он будет использовать оператор объединения нулей чтобы вернуть "" пустую строку в правой части оператора.

Пожалуйста, дайте мне знать, если я что-то упустил, так как я не могу понять, почему я получаю эту ошибку, даже при добавлении нулевого слияния оператор.

Редактировать: Как показано в комментарии, просмотр этой записи помог мне узнать больше, почему я получил эту ошибку. Хотя вопросы немного отличаются, я настоятельно рекомендую прочитать ответ, чтобы получить полное представление о моей проблеме.

Ответы [ 2 ]

7 голосов
/ 29 января 2020

наиболее вероятная причина в том, что FirstOrDefault() возвращает null (как значение по умолчанию ) и, таким образом, FirstOrDefault().Name вызывает исключение. Вы можете попробовать нулевое распространение с помощью ?.

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

Так что если approval.Results равно пусто и, следовательно, FirstOrDefault() возвращает null, тогда FirstOrDefault()?.Name возвращает null, что в конечном итоге превращается в ""

7 голосов
/ 29 января 2020

После каждого из вызовов .FirstOrDefault() необходимо добавить оператора ?.. Вот полное решение:

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

Если возможно, что другие части результатов могут быть нулевыми, вы можете go полный параноидальный маршрут

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

И параноик и LINQ-ified :

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