C# Language
Оператор Null-Coalescing
Поиск…
Синтаксис
- var result = possibleNullObject ?? значение по умолчанию;
параметры
параметр | подробности |
---|---|
possibleNullObject | Значение для проверки нулевого значения. Если значение не равно null, это значение возвращается. Должен быть тип с нулевым значением. |
defaultValue | Значение, возвращаемое, если possibleNullObject имеет значение NULL. Должен быть того же типа, что и possibleNullObject . |
замечания
Нулевой оператор коалесцирования сам по себе является двумя последовательными символами вопросительного знака: ??
Это сокращение условного выражения:
possibleNullObject != null ? possibleNullObject : defaultValue
Левый операнд (тестируемый объект) должен быть типом типа NULL или ссылочным типом, или произойдет ошибка компиляции.
The ?? оператор работает как для ссылочных типов, так и для типов значений.
Основное использование
Используя null-coalescing operator (??)
вы можете указать значение по умолчанию для типа NULL, если левый операнд имеет значение null
.
string testString = null;
Console.WriteLine("The specified string is - " + (testString ?? "not provided"));
Живая демонстрация на .NET скрипке
Это логически эквивалентно:
string testString = null;
if (testString == null)
{
Console.WriteLine("The specified string is - not provided");
}
else
{
Console.WriteLine("The specified string is - " + testString);
}
или используя оператор тернарного оператора (? :) :
string testString = null;
Console.WriteLine("The specified string is - " + (testString == null ? "not provided" : testString));
Null fall-through and chaining
Левый операнд должен быть нулевым, в то время как правый операнд может быть или не быть. Результат будет набран соответствующим образом.
Ненулевые
int? a = null;
int b = 3;
var output = a ?? b;
var type = output.GetType();
Console.WriteLine($"Output Type :{type}");
Console.WriteLine($"Output value :{output}");
Выход:
Тип: System.Int32
значение: 3
Nullable
int? a = null;
int? b = null;
var output = a ?? b;
output
будет иметь тип int?
и равна b
или null
.
Многократное объединение
Коалесцирование также может выполняться в цепях:
int? a = null;
int? b = null;
int c = 3;
var output = a ?? b ?? c;
var type = output.GetType();
Console.WriteLine($"Type :{type}");
Console.WriteLine($"value :{output}");
Выход:
Тип: System.Int32
значение: 3
Null Conditional Chaining
Оператор нулевого коалесцирования может использоваться в тандеме с оператором распространения пустоты для обеспечения более безопасного доступа к свойствам объектов.
object o = null;
var output = o?.ToString() ?? "Default Value";
Выход:
Тип: System.String
Значение: Значение по умолчанию
Оператор коллаборации с вызовом метода
Оператор null coalescing позволяет легко убедиться, что метод, который может вернуть значение null
, вернется к значению по умолчанию.
Без оператора нулевой коалесценции:
string name = GetName();
if (name == null)
name = "Unknown!";
С нулевым коалесцирующим оператором:
string name = GetName() ?? "Unknown!";
Использовать существующие или создавать новые
Обычный сценарий использования, с которым эта функция действительно помогает, - это когда вы ищете объект в коллекции и вам нужно создать новый, если он еще не существует.
IEnumerable<MyClass> myList = GetMyList();
var item = myList.SingleOrDefault(x => x.Id == 2) ?? new MyClass { Id = 2 };
Инициализация ленивых свойств с помощью оператора нулевой коалесценции
private List<FooBar> _fooBars;
public List<FooBar> FooBars
{
get { return _fooBars ?? (_fooBars = new List<FooBar>()); }
}
Первый раз , когда недвижимость .FooBars
осуществляется доступ к _fooBars
переменному будет оценивать , как null
, таким образом , падает через к правопреемникам оператора присваивания и оценивает к полученному значению.
Безопасность резьбы
Это не потокобезопасный способ реализации ленивых свойств. Для поточнобезопасной лени используйте класс Lazy<T>
встроенный в .NET Framework.
C # 6 Синтаксический сахар с использованием тел экспрессии
Обратите внимание, что с C # 6 этот синтаксис можно упростить с помощью тела выражения для свойства:
private List<FooBar> _fooBars;
public List<FooBar> FooBars => _fooBars ?? ( _fooBars = new List<FooBar>() );
Последующий доступ к свойству даст значение, хранящееся в переменной _fooBars
.
Пример в шаблоне MVVM
Это часто используется при реализации команд в шаблоне MVVM. Вместо того, чтобы инициализировать команды с помощью конструкции модели, команды инициализируются лениво, используя этот шаблон следующим образом:
private ICommand _actionCommand = null;
public ICommand ActionCommand =>
_actionCommand ?? ( _actionCommand = new DelegateCommand( DoAction ) );