This question has been completely overhauled in the interest of being thorough in explanation.
I have noticed what appears to be quite a poor limitation of the null propagation operator in C# 6.0 in that you cannot call property setters against an object that has been null propagated (though you can call property getters against an object that has been null propagated). As you will see from the generated IL (which I have reflected into C#), there is nothing that should limit the ability to call property setters using null propagation.
To start with, I have created a simple class, with both Java style Get/Set methods, and a property with public getter/setter access.
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;
}
}
I have tested the ability of null propagation in the following test class.
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;
}
}
The left-hand side of an assignment must be a variable, property or indexer.
You may notice from this however that the Java way of setting the name, by calling SetName(...)
works, and you may also notice getting the value of a null propagated property also works.
Let's take a look at the C# that was generated from this code:
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;
}
Notice that when used against the SetName
method, null propagation transforms to a straightforward if
statement, and that when used against the Name
property getter, a ternary operator is used to either get the value of Name
or null
.
One thing I have noticed here is the behavior difference between using an if
statement and using the ternary operator: when using a setter, using an if
statement would work, whereas using a ternary operator wouldn't.
public static void Main(string[] args)
{
Person person = null;
if (person != null)
{
person.Name = "John Smith";
}
person.Name = (person != null) ? "John Smith" : null;
}
In this example I am using both an if
statement and the ternary operator to check whether person is null
before attempting to assign to its Name
property. the if
statement works as expected; the statement using the ternary operator fails, as expected
Object reference not set to an instance of an object.
In my opinion, the limitation comes from C# 6.0's ability to transform null propagation into either an if
statement or a ternary expression. Had it been designed to use only if
statements, property assignment would work via null propagation.
So far, I have not seen one compelling argument as to why this SHOULD NOT be possible, therefore I am still looking for answers!
null propagation
has to do with assignment? It should be more explicit than similar names in other languages (eg. null-safe as proposed for Java, safe navigation in Groovy, safe-call in Kotlin) that it doesn't assign anything but returns (propagates) nulls if applied on a null object – LilliasomeValue
for null, it checksa
. There's no difference at all betweena.SetValue
anda?.SetValue
regarding its parameters. – Lillia