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 заявления, присвоение свойства будет работать через нулевое распространение.

До сих пор я не видел ни одного убедительного аргумента о том, почему это НЕ ДОЛЖНО быть возможным, поэтому я все еще ищу ответы!

Ответы на вопрос(3)

Ваш ответ на вопрос