Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Safe Navigation Operator in C#? [duplicate]

Tags:

c#

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.

like image 224
Kyle Avatar asked Nov 05 '10 22:11

Kyle


People also ask

What does safe navigation operator do?

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.

What is safe navigation operator C#?

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.

What is safe navigation operator in rails?

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.

What is safe navigation operator in angular?

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 .


4 Answers

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.

like image 125
flq Avatar answered Sep 22 '22 23:09

flq


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... ;-)

like image 41
stakx - no longer contributing Avatar answered Sep 23 '22 23:09

stakx - no longer contributing


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.

like image 38
Robert Harvey Avatar answered Sep 23 '22 23:09

Robert Harvey


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.)

like image 27
sblom Avatar answered Sep 23 '22 23:09

sblom