
?.: when properties in C # can be null
- Transfer
The more I write in C # 6, the more convinced in how the operator
But now we have C # 6, with it the code can be brought in a much more readable form:
The operator
Have you noticed something was wrong? The code will crash if the event has
Okay, it's gotten a little better. It is possible that this code will work in most cases. However, nobody canceled the race condition: if the subscriber unsubscribes from the event at the moment after we check
Oh, there’s a lot of code, it’s hard to remember all this and call it
The code is shorter, easier to read, all necessary checks are performed, there are no problems.
The operator
Case two: I want to return a value
?.
( null Coalescing of operator ) helps to write a clean simple and intuitive code. Today I will show 4 situations in which it can be very useful.Large nesting
Consider the following problem. There is a supplier, the supplier has a contact person, the contact person has a home address, the home address has the first line, and we want to find this very first line. Before, I would have to write code with a high level of nesting, checking fornull
each value in the chain:var location = default(string);
if (vendor != null)
{
if (vendor.ContactPerson != null)
{
if (vendor.ContactPerson.HomeAddress != null)
{
location = vendor.ContactPerson.HomeAddress.LineOne;
}
}
}
But now we have C # 6, with it the code can be brought in a much more readable form:
var location = vendor?.ContactPerson?.HomeAddress?.LineOne;
The operator
?.
will make it so that as soon as one of the properties of the chain appears null
, no further calculation of the expression will be performed. Let's see a few more examples.INotifyPropertyChanged and related APIs
We have all seen the classes that implement the interfaceINotifyPropertyChanged
. In them you can find properties of the following type:public string Name {
get { return name; }
set {
if (name != value)
{
name = value;
PropertyChanged(this, new PropertyChangedEventArgs("Name"));
}
}
}
private string name;
Have you noticed something was wrong? The code will crash if the event has
INotifyPropertyChanged.PropertyChanged
no subscribers. In this situation, many developers begin to write like this:public string Name {
get { return name; }
set {
if (name != value)
{
name = value;
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs("Name"));
}
}
}
private string name;
Okay, it's gotten a little better. It is possible that this code will work in most cases. However, nobody canceled the race condition: if the subscriber unsubscribes from the event at the moment after we check
PropertyChanged != null
, but before it is called PropertyChanged
, then the program will still crash. And this will happen at the most inopportune moment a few months after installing the application on the client. Let's fix this annoying problem: save a link to PropertyChnaged
a local variable, handler
check it on null
, after which we will work with this local variable, and not with a public event PropertyChnaged
:public string Name {
get { return name; }
set {
if (name != value)
{
name = value;
var handler = PropertyChanged;
if (handler != null)
handler(this, new PropertyChangedEventArgs("Name"));
}
}
}
private string name;
Oh, there’s a lot of code, it’s hard to remember all this and call it
PropertyChanged
correctly every time . In a large program, someone somewhere will surely forget to do all the checks. What to do? C # 6 will save us! All of our checks are easily replaced using the operator ?.
and method call Invoke
:public string Name {
get { return name; }
set {
if (name != value)
{
name = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Name"));
}
}
}
private string name;
The code is shorter, easier to read, all necessary checks are performed, there are no problems.
Resource management
And now this situation: there is an object of some type, the description of which we know. You need to understand that this object can implement interfaces that the type is not aware of. This is usually not such a problem, but what if the object implementsIDisposable
. Imagine an evil genius who decided to retire one of his minions. The corresponding code will look like this:public void RetireHenchman()
{
var disposableMinion = Minion as IDisposable;
if (disposableMinion != null)
disposableMinion.Dispose();
Minion = null;
}
The operator
?.
will again help improve the quality of our code:public void RetireHenchman()
{
(Minion as IDisposable)?.Dispose();
Minion = null;
}
LINQ queries
I found two cases where a statement?.
can be useful in LINQ queries. Case one: I want to create a query using the method SingleOrDefault()
, and for the received object (if it exists), turn to some property. Nothing is easier:var created = members.SingleOrDefault(e => e.name == "dateCreated")?.content;
Case two: I want to return a value
null
if the original sequence is null
:members?.Select(m => (XElement)XmlValue.MakeValue(m))
Conclusion
Adding the operator in question made me realize how often there are checks onnull
and how much shorter and more readable the code can be made using the new syntax. Thanks, ?.
I began to write code differently. I can’t wait until the final release of C # 6 is released so that I can give my customers a new version of the source.