Pregunta

I have a class with a string property. I use the coalesce operator when reading from it as it might be null, but it still throws me an NullRefrenceExeption.

string name = user.Section.ParentSection.Name ?? string.Empty;

To be more specific, its the ".ParentSection" that's null so is it because it don't even have ".name" ? If that's the case should i test ".ParentSection" first with an if block?

I assume there are something about the Coalesce operator i dont understand, hope someone can shed some light on whats going wrong here.

¿Fue útil?

Solución

To be more specific, its the ".ParentSection" that's null so is it because it don't even have ".name" ?

Yes.

If that's the case should i test ".ParentSection" first with an if block?

Yes.

Otros consejos

You'll need to check if Section and ParentSection are null. You could use an if-statement for this or write an extension method like this:

public static class MaybeMonad
{
    public static TOut With<TIn, TOut>(this TIn input, Func<TIn, TOut> evaluator)
        where TIn : class
        where TOut : class
    {
        if (input == null)
        {
            return null;
        }
        else
        {
            return evaluator(input);
        }
    }
}

You would use this method like so:

string name = user.With(u => u.Section)
                  .With(s => s.ParentSection)
                  .With(p => p.Name) ?? string.Empty;

I think it's a lot cleaner than an if-statement with a lot of &&.

Some further reading: http://www.codeproject.com/Articles/109026/Chained-null-checks-and-the-Maybe-monad

You need to check if user, user.Section, or user.Section.ParentSection are null before you can use the null coalescing operator on a property of user.Section.ParentSection.

Nested property access is not safe if any of the objects accessed are null this will throw a NullReferenceException. You will have to explicitly test for the outer objects to be not null.

E.g.:

string name = string.Empty;
if(user!=null && user.Section!=null && user.Section.ParentSection !=null)
   name = user.Section.ParentSection.Name ?? string.Empty;

In general I would try to avoid nested access to properties, you are violating the Law of Demeter. Some refactoring might make this unnecessary in the first place.

The ?? operator checks if the left side is null and if so returns the right one, if not the left one. In your case the left-side is the "Name" property in the object user.Section.ParentSection and this is null.

In those cases either think on what might be null or do something like this:

string name = user == null 
              || user.Section == null 
              || user.ParentSection == null 
              || user.Section.ParentSection.Name == null 
                 ? string.Empty 
                 : user.Section.ParentSection.Name;

(yeah it's ugly I know)

Chances are user or user.Section or user.Section.ParentSection is a null value.

The ?? operator doesn't prevent checks like:

if (user != null && user.Section != null && user.Section.ParentSection != null){

Make sure that everything up to the string property is valid and exists, then you can use ??. You can't call (null).Name, no matter how many times you try.

Yes you need to check if Section or ParentSection are null before you check Name

It is probably best to do something like this:

if(user!=null && user.Section!=null && user.Section.ParentSection!=null)
{
     string name = user.Section.ParentSection.Name ?? string.Empty;
}

The null coalescing operator takes a statement like:

a = b ?? c;  

What this says is "evaluate b; if it has a non-null value then assign that to a. Otherwise assign the value of c to a".

However within your b you're using a user object which may be null that has a section object that may be null that has a parent section property that may be null that had a name property that may be null. If you wanted to check all of these (and typically you should) then you can do something like:

string name = string.Empty;  
if (user != null &&  
     user.Section != null &&  
     user.Section.ParentSection != null)  
{  
  name = user.Section.ParentSection.Name ?? string.Empty;  
}

As soon as the IF check fails it will not check further and therefore you don't get a NullReferenceException when you assume an object is present and then try to access one of its properties.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top