Possible Duplicate:
Shortcut for “null if object is null, or object.member if object is not null”
Some languages have a safe navigation operator that lets you not worry about null reference exceptions.
Example of the language Groovy:
String lname = person.Name.ToLowerCase(); //throws exception if Name is null
String lname = person.Name?.ToLowerCase();//lname will be null if Name was null
How can I accomplish something similar to this in C#? My solution so far is an extension method like this:
public static T o<T>(this T obj) where T : new()
{
return obj != null ? obj : new T();
}
//used like: String lname = person.o().Name; //returns null if person was null
However, this only works in some cases.
Use the safe navigation operator ( ?. ) to replace explicit, sequential checks for null references. This operator short-circuits expressions that attempt to operate on a null value and returns null instead of throwing a NullPointerException.
C# 6.0 includes a new null-conditional operator (sometimes called the Safe Navigation Operator): In previous versions null checking for any kind of objects manually we need to write if condition then we need to write our required properties or else we need to write our business logic.
Safe navigation operator¶ ↑ &. , called “safe navigation operator”, allows to skip method call when receiver is nil . It returns nil and doesn't evaluate method's arguments if the call is skipped.
The Angular safe navigation operator, ? , guards against null and undefined values in property paths. Here, it protects against a view render failure if item is null .
For such cases I tend to use an extension method called IfNotNull
:
public static OUT IfNotNull<IN, OUT>(this IN v, Func<IN, OUT> f)
where IN : class where OUT : class
{
return v == null ? null : f(v);
}
More sophisticated is to introduce the notion of a Maybe . An example was brought by derick bailey here.
Update:
As of C# 6 there is now a null-propagating operator which syntax-wise looks exactly like the Groovy one.
You are looking for the short-circuiting null-conditional member access operator ?.
that was introduced in C# language version 6 (rolled out in Visual Studio 2015).
The remainder of my answer was written for earlier versions of the C# language which did not have the ?.
operator.
Generally speaking, if you're in a situation where you are accessing a deeply "nested" property, such as outermostObject.a.b.c.X
, you should probably consider re-designing your code, as such an access could indicate that you're violating established OO principles (such as the principle of least knowledge, a.k.a. Law of Demeter).
Some other options:
First, an anti-suggestion — don't do this:
string lname = null;
try
{
lname = Person.Name.ToLower();
}
catch (NullReferenceException ex) { } // inefficient and ugly
Second, using something like a Maybe
monad — you can define such a type yourself. It's basically a Nullable<T>
that implements IEnumerable<T>
such that it returns an empty sequence when no value is set, or a sequence of exactly one element if a value is set. You'd then use it as follows:
Maybe<string> personName = person.Name;
var lname = (from name in personName select name.ToLower()).FirstOrDefault();
Third, and probably the easiest and most practical solution, as suggested by ulrichb:
var lname = person.Name != null ? person.Name.ToLower() : null;
P.S., since we're already on the topic of checking for null
, don't forget to check whether person
is null
before accessing its Name
property... ;-)
I don't know about returning a null from something that's guaranteed to not be null, but for guaranteeing an object reference, you can use the Null Coalescing Operator ??
Something like:
string lname = (person.Name??String.Empty).ToLower();
It will return an empty string instead of null for the null case, but it will work.
Returning an empty string makes more sense than returning a null; if you return a null, it will throw again if you chain another operator onto it.
Doesn't exist in C# today, but you can write it with SelectMany
.
String lname = from _ in person.Name from s in _.ToUpper() select s;
or
String lname = person.Name.SelectMany(_ => _.ToUpper(), s => s);
(That was Bart De Smet's proposal in his PDC 2010 talk on the future of LINQ. See slide #6.)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With