C # 6.0 Нулевой оператор распространения и присвоение свойства
Этот вопрос был полностью пересмотрен в интересах подробного объяснения.
Я заметил то, что кажется довольно слабым ограничением оператора распространения нуля в C # 6.0 в том, что вы не можете вызывать свойствосеттеры против объекта, который был передан нулевым значением (хотя вы можете вызвать свойстводобытчики против объекта, который был передан нулевым). Как вы увидите из сгенерированного IL(который я отразил в C #), нет ничего, что должно ограничивать способность вызывать установщики свойств с использованием нулевого распространения.
Для начала я создал простой класс с методами Get / Set в стиле Java и свойством с общедоступным доступом для получения / установки.
public class Person
{
public Person(string name, DateTime birthday)
{
Name = name;
}
public string Name { get; set; }
public void SetName(string name)
{
Name = name;
}
public string GetName()
{
return Name;
}
}
Я проверил способность нулевого распространения в следующем тестовом классе.
public class Program
{
public static void Main(string[] args)
{
Person person = new Person("Joe Bloggs", DateTime.Parse("01/01/1991"));
// This line doesn't work - see documented error below
person?.Name = "John Smith";
person?.SetName("John Smith");
string name = person?.Name;
}
}
Левая часть присваивания должна быть переменной, свойством или индексатором.
Из этого, однако, вы можете заметить, что Java-способ установки имени, вызываяSetName(...)
работает, и вы также можете заметить, что получение значения свойства с нулевым распространением также работает.
Давайте посмотрим на C #, который был сгенерирован из этого кода:
public static void Main(string[] args)
{
Person person = new Person("Joe Bloggs", DateTime.Parse("01/01/1991"));
if (person != null)
{
person.SetName("John Smith");
}
string arg_33_0 = (person != null) ? person.Name : null;
}
Обратите внимание, что при использовании противSetName
метод, нулевое распространение превращается в простойif
заявление, и что при использовании противName
для получения свойства, троичный оператор используется либо для получения значенияName
или жеnull
.
Одна вещь, которую я заметил здесь, это разница в поведении между использованиемif
оператор и использование троичного оператора: при использовании сеттера, используяif
оператор будет работать, в то время как использование троичного оператора не будет.
public static void Main(string[] args)
{
Person person = null;
if (person != null)
{
person.Name = "John Smith";
}
person.Name = (person != null) ? "John Smith" : null;
}
В этом примере я использую обаif
заявление и троичный оператор, чтобы проверить, является ли человекnull
прежде чем пытаться присвоить егоName
имущество.if
выписка работает как положено; оператор с использованием тернарного оператора завершается неудачно, как и ожидалось
В экземпляре объекта не задана ссылка на объект.
На мой взгляд, ограничение исходит из способности C # 6.0 преобразовывать нулевое распространение вif
утверждение или троичное выражение. Если бы он был предназначен для использования толькоif
заявления, присвоение свойства будет работать через нулевое распространение.
До сих пор я не видел ни одного убедительного аргумента о том, почему это НЕ ДОЛЖНО быть возможным, поэтому я все еще ищу ответы!