Null propagation C# with Example



Null propagation C# with Example

The ?. operator and ?[...] operator are called the null-conditional operator. It is also sometimes referred to by 
other names such as the safe navigation operator. 
This is useful, because if the . (member accessor) operator is applied to an expression that evaluates to null, the 
program will throw a NullReferenceException. If the developer instead uses the ?. (null-conditional) operator, the 
expression will evaluate to null instead of throwing an exception. 
Note that if the ?. operator is used and the expression is non-null, ?. and . are equivalent. 
Basics 
var teacherName = classroom.GetTeacher().Name; 
// throws NullReferenceException if GetTeacher() returns null 
View Demo 
If the classroom does not have a teacher, GetTeacher() may return null. When it is null and the Name property is 
accessed, a NullReferenceException will be thrown. 
If we modify this statement to use the ?. syntax, the result of the entire expression will be null: 
var teacherName = classroom.GetTeacher()?.Name; 
// teacherName is null if GetTeacher() returns null 
View Demo 
Subsequently, if classroom could also be null, we could also write this statement as: 
var teacherName = classroom?.GetTeacher()?.Name; 
// teacherName is null if GetTeacher() returns null OR classroom is null 
View Demo 
This is an example of short-circuiting: When any conditional access operation using the null-conditional operator 
evaluates to null, the entire expression evaluates to null immediately, without processing the rest of the chain. 
When the terminal member of an expression containing the null-conditional operator is of a value type, the 
expression evaluates to a Nullable of that type and so cannot be used as a direct replacement for the 
expression without ?.. 
bool hasCertification = classroom.GetTeacher().HasCertification; 
// compiles without error but may throw a NullReferenceException at runtime 
bool hasCertification = classroom?.GetTeacher()?.HasCertification; 
// compile time error: implicit conversion from bool? to bool not allowed 
bool? hasCertification = classroom?.GetTeacher()?.HasCertification; 
// works just fine, hasCertification will be null if any part of the chain is null 
 

bool hasCertification = classroom?.GetTeacher()?.HasCertification.GetValueOrDefault(); 
// must extract value from nullable to assign to a value type variable 
Use with the Null-Coalescing Operator (??) 
You can combine the null-conditional operator with the Null-coalescing Operator (??) to return a default value if the 
expression resolves to null. Using our example above: 
var teacherName = classroom?.GetTeacher()?.Name ?? "No Name"; 
// teacherName will be "No Name" when GetTeacher() 
// returns null OR classroom is null OR Name is null 
Use with Indexers 
The null-conditional operator can be used with indexers: 
var firstStudentName = classroom?.Students?[0]?.Name; 
In the above example: 
The first ?. ensures that classroom is not null. 
The second ? ensures that the entire Students collection is not null. 
0
The third ?. after the indexer ensures that the [ ] indexer did not return a null object. It should be noted 
that this operation can still throw an IndexOutOfRangeException. 
Use with void Functions 
Null-conditional operator can also be used with void functions. However in this case, the statement will not 
evaluate to null. It will just prevent a NullReferenceException. 
List list = null; 
list?.Add("hi"); // Does not evaluate to null 
Use with Event Invocation 
Assuming the following event definition: 
private event EventArgs OnCompleted; 
When invoking an event, traditionally, it is best practice to check if the event is null in case no subscribers are 
present: 
var handler = OnCompleted; 
if (handler != null) 
{ 
handler(EventArgs.Empty); 
} 
Since the null-conditional operator has been introduced, the invocation can be reduced to a single line: 
OnCompleted?.Invoke(EventArgs.Empty); 
Limitations 
 

Null-conditional operator produces rvalue, not lvalue, that is, it cannot be used for property assignment, event 
subscription etc. For example, the following code will not work: 
// Error: The left-hand side of an assignment must be a variable, property or indexer 
Process.GetProcessById(1337)?.EnableRaisingEvents = true; 
// Error: The event can only appear on the left hand side of += or -= 
Process.GetProcessById(1337)?.Exited += OnProcessExited; 
Gotchas 
Note that: 
int? nameLength = person?.Name.Length; // safe if 'person' is null 
is not the same as: 
int? nameLength = (person?.Name).Length; // avoid this 
because the former corresponds to: 
int? nameLength = person != null ? (int?)person.Name.Length : null; 
and the latter corresponds to: 
int? nameLength = (person != null ? person.Name : null).Length; 
Despite ternary operator ?: is used here for explaining the difference between two cases, these operators are not 
equivalent. This can be easily demonstrated with the following example: 
void Main() 
{ 
var foo = new Foo(); 
Console.WriteLine("Null propagation"); 
Console.WriteLine(foo.Bar?.Length); 
Console.WriteLine("Ternary"); 
Console.WriteLine(foo.Bar != null ? foo.Bar.Length : (int?)null); 
} 
class Foo 
{ 
public string Bar 
{ 
get 
{ 
Console.WriteLine("I was read"); 
return string.Empty; 
} 
} 
} 
Which outputs: 
Null propagation 
I was read 
0 
 

Ternary 
I was read 
I was read 
0 
View Demo 
To avoid multiple invocations equivalent would be: 
var interimResult = foo.Bar; 
Console.WriteLine(interimResult != null ? interimResult.Length : (int?)null); 
And this difference somewhat explains why null propagation operator is not yet supported in expression trees. 

0 Comment's

Comment Form

Submit Comment