Нет, это исключение нулевой ссылки, точно так же, как доступ к var x = u.Address.Country.Code;
будет NullReferenceException
.
Вы всегда должны убедиться, что в LINQ к объектам вы не обращаетесь к null
, как это было бы с любыми другими операторами кода.
Вы можете сделать это либо с помощью имеющейся у вас логики &&
, либо с помощью цепочки предложений Where
(хотя это будет содержать больше итераторов и, вероятно, работать медленнее):
var result = Users.Where(u => u.Address != null)
.Where(u.Address.Country != null)
.Where(u.Address.Country.Code == 12);
ПРИМЕЧАНИЕ : метод Maybe()
, представленный ниже, просто предлагается как метод «Вы также можете», я не говорю, хорошо это или плохо, просто показываю, что делают некоторые люди. Пожалуйста, не голосуйте, если вам не нравится Maybe()
Я просто повторяю различные решения, которые я видел ...
Я видел несколько написанных Maybe()
методов расширения, которые позволяют вам делать то, что вы хотите. Некоторым людям это нравится / не нравится, потому что они являются методами расширения, работающими с ссылкой null
. Я не говорю, что это хорошо или плохо, просто некоторые люди считают, что это нарушает хорошее ОО-подобное поведение.
Например, вы можете создать метод расширения, например:
public static class ObjectExtensions
{
// returns default if LHS is null
public static TResult Maybe<TInput, TResult>(this TInput value, Func<TInput, TResult> evaluator)
where TInput : class
{
return (value != null) ? evaluator(value) : default(TResult);
}
// returns specified value if LHS is null
public static TResult Maybe<TInput, TResult>(this TInput value, Func<TInput, TResult> evaluator, TResult failureValue)
where TInput : class
{
return (value != null) ? evaluator(value) : failureValue;
}
}
А затем сделайте:
var result = Users.Where(u => u.Maybe(x => x.Address)
.Maybe(x => x.Country)
.Maybe(x => x.Code) == 12);
По сути, это просто каскад null
вниз по цепочке (или значение по умолчанию в случае не ссылочного типа).
UPDATE
Если вы хотите указать значение ошибки, отличное от значения по умолчанию (скажем, Код равен -1, если какая-либо часть имеет значение null), вы просто передадите новое значение ошибки в Maybe ():
// if you wanted to compare to zero, for example, but didn't want null
// to translate to zero, change the default in the final maybe to -1
var result = Users.Where(u => u.Maybe(x => x.Address)
.Maybe(x => x.Country)
.Maybe(x => x.Code, -1) == 0);
Как я уже сказал, это только одно из многих решений. Некоторым людям не нравится возможность вызывать методы расширения из null
ссылочных типов, но некоторые люди склонны использовать эту возможность, чтобы обойти эти null
каскадные проблемы.
В настоящее время, однако, в C # не встроен нулевой безопасный оператор де-ссылки, поэтому вы либо используете условные проверки нуля, как вы делали это раньше, объединяйте свои операторы Where()
в цепочку, чтобы они отфильтровывали null
, или создайте что-нибудь, чтобы позволить вам каскадно null
как Maybe()
методы выше.