Elegant way to avoid a NullReferenceException in C #

I want to do it

var path = HttpContext.Current.Request.ApplicationPath; 

If any of the properties on the path is null, I want the path to be empty, or "" would be better.

Is there an elegant way to do this without triple?

Ideally, I would like this behavior (without terrible performance and ugliness) a line of the way;

 try { path = HttpContext.Current.Request.ApplicationPath; } catch { path = null; } 

thanks

+7
source share
5 answers

[EDIT]

C # 6 was released some time ago and it comes with an empty statement ?. that will simplify your case:

 var path = HttpContext?.Current?.Request?.ApplicationPath 

For historical reasons, the answer to previous language versions can be found below.


I assume you are looking for a Groovy safe dereferencing operator ?. and you are not the first. From a related topic, the solution that I personally like most is this ( that one of them looks good), then you can simply do:

 var path = HttpContext.IfNotNull(x => x.Current).IfNotNull(x => x.Request).IfNotNull(x => x.ApplicationPath); 

You can always shorten a function name a bit. This will return null if any of the objects in the expression is null, ApplicationPath otherwise. For value types, you will need to perform one null check at the end. In any case, there is no other way, if you do not want to check the null value at each level.

The extension method used above is used here:

  public static class Extensions { // safe null-check. public static TOut IfNotNull<TIn, TOut>(this TIn v, Func<TIn, TOut> f) where TIn : class where TOut: class { if (v == null) return null; return f(v); } } 
+11
source

UPDATE (November 2014)

C # 6 contains something called the zero propagation operator , which means that there is language support for this. Your example can be written in C # 6 as follows:

 var path = HttpContext?.Current?.Request?.ApplicationPath; 

If any part contains zero, the full expression will return zero.


You can write something like this:

 string value = NullHelpers.GetValueOrNull( () => HttpContext.Current.Request.ApplicationPath); 

The easiest way to implement this is NullHelpers.GetValueOrNull is something like this:

 public static T GetValueOrNull<T>(Func<T> valueProvider) where T : class { try { return valueProvider(); } catch (NullReferenceException) { return null; } } 

But by far the coolest way to solve this problem is to use expression trees:

 public static T GetValueOrNull<T>( Expression<Func<T>> valueProvider) where T : class { var expression = (MemberExpression) ((MemberExpression)valueProvider.Body).Expression; var members = new List<MemberExpression>(); while (expression != null) { members.Add(expression); expression = (MemberExpression)expression.Expression; } members.Reverse(); foreach (var member in members) { var func = Expression.Lambda<Func<object>>(member).Compile(); if (func() == null) { return null; } } return valueProvider.Compile()(); } 

This is also the slowest way to do something, since each call will make one or more calls to the JIT compiler, but ...

It's still cool ;-)

+4
source

The shortest and most efficient way is to perform a zero check at each level. For reuse, you can wrap this code in a helper function, or perhaps an extension method. This will allow you to safely access it through this function, but will still perform a zero check.

Example:

 public void DoSomething() { // Get the path, which may be null, using the extension method var contextPath = HttpContext.Current.RequestPath; } public static class HttpContextExtensions { public static string RequestPath(this HttpContext context) { if (context == null || context.Request == null) { return default(string); } return context.Request.ApplicationPath; } } 
+2
source

In May 2012, when you asked a question, I did not see a simpler solution than trying ... to catch you. The only alternative is to check each part against zero with "if" or "?" looked ugly (but maybe a little faster).

Or you had to write:

 path = HttpContext!=null ? (HttpContext.Current!=null ? (HttpContext.Current.Request!=null ?(HttpContext.Current.Request.ApplicationPath!=null ? HttpContext.Current.Request.ApplicationPath : null) : null) : null) : null; 

or

 if (HttpContext == null || HttpContext.Current == null || HttpContext.Current.Request == null || HttpContext.Current.Request.ApplicationPath == null) path = null; else path = HttpContext.Current.Request.ApplicationPath; 

both do this without exception handling. Note that both methods use shortcuts to abort the check if a null value is found.


Update (December 2017): Since C # Version 6 and above , a better solution is available, the so-called Elvis Operator (also known as the zero-coalescing operator ?. And x?[i] for arrays), which you can use. Example above

 path = HttpContext!=null ? (HttpContext.Current!=null ? (HttpContext.Current.Request!=null ?(HttpContext.Current.Request.ApplicationPath!=null ? HttpContext.Current.Request.ApplicationPath : null) : null) : null) : null; 

It looks much better:

 path = HttpContext?.Current?.Request?.ApplicationPath; 

which does the same thing and IMHO is much more than just syntactic sugar. Combined with the added ?? value ?? value you can easily replace null with another value, for example.

 path = (HttpContext?.Current?.Request?.ApplicationPath) ?? ""; 

This makes the path variable empty if a nonzero value cannot be obtained.

+2
source

In C # 7.0

You can also use the exclamation mark "! To avoid null values

 MyClass a; // Nullable reference type MyClass! b; // Non-nullable reference type a = null; // OK, this is nullable b = null; // Error, b is non-nullable b = a; // Error, n might be null, s can't be null WriteLine(b.ToString()); // OK, can't be null WriteLine(a.ToString()); // Warning! Could be null! if (a != null) { WriteLine(a.ToString); } // OK, you checked 
+1
source

All Articles