Этот вопрос был полностью пересмотрен в интересах тщательного объяснения.
Я заметил, что, по-видимому, довольно плохое ограничение оператора распространения NULL в С# 6.0 тем, что вы не можете вызвать свойство seters для объекта, который был распространен в NULL (хотя вы можете вызвать свойство getters против объекта, который был передан в ноль). Как вы увидите из сгенерированного ИЛ (который я отразил на С#), нет ничего, что должно было бы ограничить возможность вызова средств определения свойств с использованием нулевого распространения.
Для начала я создал простой класс с использованием методов Get/Set в стиле Java и свойства с открытым доступом к getter/setter.
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(...)
, работает, и вы также можете заметить, что также работает значение свойства, распространяемого в нуле.
Посмотрим на С#, который был сгенерирован из этого кода:
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
преобразование в null преобразуется в простой оператор if
и что при использовании против getter Name
свойство тернарного оператора используется либо для получения значения Name
или null
.
Одна вещь, которую я заметил здесь, - это разница в поведении между использованием оператора if
и использованием тернарного оператора: при использовании setter использование оператора 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
работает, как ожидалось; утверждение, использующее тернарный оператор, терпит неудачу, как ожидалось
Ссылка на объект не установлена в экземпляр объекта.
На мой взгляд, ограничение связано с возможностью С# 6.0 преобразовывать нулевое распространение в оператор if
или тройное выражение. Если бы он был разработан для использования только операторов if
, присвоение свойств работало бы с помощью пустого распространения.
До сих пор я не видел одного убедительного аргумента относительно того, почему это НЕ ДОЛЖНО быть возможным, поэтому я все еще ищу ответы!