184

Suppose, I have this interface,

interface IContact
{
    IAddress address { get; set; }
}

interface IAddress
{
    string city { get; set; }
}

class Person : IPerson
{
    public IContact contact { get; set; }
}

class test
{
    private test()
    {
        var person = new Person();
        if (person.contact.address.city != null)
        {
            //this will never work if contact is itself null?
        }
    }
}

Person.Contact.Address.City != null (This works to check if City is null or not.)

However, this check fails if Address or Contact or Person itself is null.

Currently, one solution I could think of was this:

if (Person != null && Person.Contact!=null && Person.Contact.Address!= null && Person.Contact.Address.City != null)

{ 
    // Do some stuff here..
}

Is there a cleaner way of doing this?

I really don't like the null check being done as (something == null). Instead, is there another nice way to do something like the something.IsNull() method?

Karthik AMR
  • 1,694
  • 21
  • 29
  • 1
    There's no such thing as safe null-dereferencing. You either have to use a custom `Option`/`Maybe` type for that or go for a null-safe extension (which is a kind-of option type as far as 'safe' dereferencing goes) – Patryk Ćwiek Jul 16 '13 at 09:16
  • 7
    what's not "clean" about what you have suggested? You're looking to save keystrokes? – Asken Jul 16 '13 at 09:16
  • @PatrykĆwiek: Are you suggesting an extension method ? Can you please give some examples so that i can understand your answer? BTW, what's a monad? – now he who must not be named. Jul 16 '13 at 09:17
  • 1
    @Asken: Yes, kind of. When I look at my code sometimes, it feels bad seeing some (something == null). How nicer would this be : if (isnull(something)) or if (something.isnull()) ? – now he who must not be named. Jul 16 '13 at 09:19
  • 59
    You code would be cleaner if it didn't violate the [Law of Demeter](http://en.wikipedia.org/wiki/Law_of_Demeter) – Dave Hillier Jul 16 '13 at 10:04
  • 4
    you could improve your engineering by extending the interface IContact with IAddress, rather than using an instance of it. same for Iperson. C# allows this: interface IContact : IAddress ... interface IPerson : IContact ... class Person : IPerson this way you can access Person.City – Koryu Jul 16 '13 at 11:15
  • 1
    @Koryu What then if you ever want to add an [`InCaseOfEmergency`](https://en.wikipedia.org/wiki/In_case_of_emergency) to `Person`? – user Jul 16 '13 at 12:53
  • @Michael What do you mean with "add an InCaseofEmergency"? – Koryu Jul 16 '13 at 14:16
  • @Koryu I mean that inheritance to bring in the fields from IContact becomes a lot harder if you want to add a second IContact to the same Person class. As in, perhaps you want one regular contact and one ICE contact. (Hint: InCaseOfEmergency is a link to Wikipedia.) The same principle applies to other combinations as well. – user Jul 16 '13 at 14:18
  • @Michael got your point. a person having two or more contacts would need a collection "additional contacts" type of Icontact for the ICEs within Person. so the inheritance wouldnt be the cleanest way here. – Koryu Jul 16 '13 at 14:36
  • 2
    @DaveHillier This is borderline. In the case where the full schema of the data is exposed as value objects, you can query it directly because you're not really creating anymore dependency, it's simply the data schema. You can argue that the interfaces hide the impl, but from this code I'd argue that interfaces for data objects are just silly. – Nick Larsen Jul 16 '13 at 14:38
  • @NickLarsen if its simple data you'd want to validate it when the data objects are constructed, or as constraints on your DB. – Dave Hillier Jul 16 '13 at 20:08
  • Your example doesn't make any sense. If person has contact why is it possible to not have address? If it has address why is it possible to not have city? And why are those interfaces? – Piotr Perak Jul 16 '13 at 20:21
  • Law of Demeter and NullObject Pattern to the rescue! – Piotr Perak Jul 16 '13 at 20:24
  • `Something.IsNull()` would throw a `NullReferenceException` if `Something` is `null`. – Geeky Guy Jul 16 '13 at 20:57
  • 1
    It is often discussed if it would be a good idea to introduce a **"safe de-reference"** operator called `?.` in C# and similar languages. It should work like the usual `.` operator except if some reference is `null` it should not throw but silently return `null`. More precise rules could be specified. Then something like `person ?. contact ?. address ?. city` would never throw, no matter in what "level" something becomes `null`. See linked threads, or google _safe dereferencing_. – Jeppe Stig Nielsen Jul 16 '13 at 21:08
  • 4
    @Peri: Do you want to make it a requirement of the data model that in order to be a person, the system must know their address? What if their address is a secret? Or they're homeless? Do you believe that all addresses have a city? What about people who live aboard air craft carriers? What city are they in? You should read http://www.mjt.me.uk/posts/falsehoods-programmers-believe-about-addresses/ – Eric Lippert Jul 16 '13 at 22:20
  • @Eric: No. I thought I was clear. What's the point of setting Contact if the only property of it (Address) will be null? Same goes for Address. Why set it if it's only property (city) will be null? This code may be stripped down but then I don't think poster can expect good answers. Right now he's asking for shortcut methods that do exactly what he does when in fact having to do this at all may be a problem. – Piotr Perak Jul 17 '13 at 11:06
  • Properties in C# are Pascal case (naming guidelines) http://msdn.microsoft.com/en-us/library/ms229043.aspx – polkduran Jul 17 '13 at 11:30
  • Since this question is on hold, would it be appropriate to migrate it to Code Review SE or Programmers SE, where these kinds of coding conventions questions are on topic? – Kevin Jul 17 '13 at 22:40
  • Marked as duplicated and the original question didn't get this much attention :) – Alaa Jabre Jul 21 '13 at 12:23
  • 3
    @nowhewhomustnotbenamed. [Null propagation](https://roslyn.codeplex.com/discussions/540883) is planned as a future C# feature. – Adam Houldsworth Apr 28 '14 at 08:08
  • 4
    I know this question is marked for .net4 and 4.5 but it's worth pointing out that c# 6 has a new null-conditional operator: `Console.WriteLine( a?.B?.C?.Town ?? "Town is null.");` – tymtam Mar 17 '16 at 02:15
  • How about `value.CheckNotNull(nameof(value))` using these extension methods https://github.com/mysteryx93/HanumanInstitute.Validators – Etienne Charland Oct 29 '20 at 00:45

19 Answers19

235

In a generic way, you may use an expression tree and check with an extension method:

if (!person.IsNull(p => p.contact.address.city))
{
    //Nothing is null
}

Full code:

public class IsNullVisitor : ExpressionVisitor
{
    public bool IsNull { get; private set; }
    public object CurrentObject { get; set; }

    protected override Expression VisitMember(MemberExpression node)
    {
        base.VisitMember(node);
        if (CheckNull())
        {
            return node;
        }

        var member = (PropertyInfo)node.Member;
        CurrentObject = member.GetValue(CurrentObject,null);
        CheckNull();
        return node;
    }

    private bool CheckNull()
    {
        if (CurrentObject == null)
        {
            IsNull = true;
        }
        return IsNull;
    }
}

public static class Helper
{
    public static bool IsNull<T>(this T root,Expression<Func<T, object>> getter)
    {
        var visitor = new IsNullVisitor();
        visitor.CurrentObject = root;
        visitor.Visit(getter);
        return visitor.IsNull;
    }
}

class Program
{
    static void Main(string[] args)
    {
        Person nullPerson = null;
        var isNull_0 = nullPerson.IsNull(p => p.contact.address.city);
        var isNull_1 = new Person().IsNull(p => p.contact.address.city);
        var isNull_2 = new Person { contact = new Contact() }.IsNull(p => p.contact.address.city);
        var isNull_3 =  new Person { contact = new Contact { address = new Address() } }.IsNull(p => p.contact.address.city);
        var notnull = new Person { contact = new Contact { address = new Address { city = "LONDON" } } }.IsNull(p => p.contact.address.city);
    }
}
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Toto
  • 7,491
  • 18
  • 50
  • 72
  • Love it. Came halfway to this With extension Methods, but using Expressions makes it totally sweet! – Peter Lillevold Jul 16 '13 at 12:09
  • Isn't your `if` reversed? `if(person.IsNull(...)) {/* Something is null */} else {/* Nothing is null */}` – Kobi Jul 16 '13 at 12:57
  • Is there an equivalent in java? – sjakubowski Jul 16 '13 at 13:10
  • 1
    @Kobi, indeed : edited – Toto Jul 16 '13 at 13:13
  • 67
    Is this really considered cleaner? – ClassicThunder Jul 16 '13 at 13:35
  • 23
    So basically, the vibe I am getting is, "No, there is no cleaner way!" – Jeff Jul 16 '13 at 14:14
  • 7
    @ClassicThunder Cleaner for the consumer, for certain. – Remi Despres-Smyth Jul 16 '13 at 14:26
  • 1
    I also agree that it's cleaner, especially if you have a lot of null checks in your code. And sometimes you are using third party libraries, which can mean you can't really modify the types. But how does it perform in comparison to the original, verbose null check of the OP? – Boluc Papuccuoglu Jul 16 '13 at 14:37
  • I've seen the functional language solving this problem beautifully. – Nawaz Jul 16 '13 at 15:24
  • Looks like you're missing the Visit() function in your code snippet. But I can imagine what it does. Just have to add in support for Indexers and field expressions and you'd have a nice utility. Also you have to add the caveat that the Properties should be zero side effect properties (I.E. getting them in succession should return the same result.) – Michael Brown Jul 16 '13 at 15:58
  • 13
    This needs to make it into the framework...maybe even as an operator. – Chris B. Behrens Jul 16 '13 at 17:36
  • 1
    `IsNull` seems an inadequate name. – Jake Berger Jul 16 '13 at 19:05
  • 2
    You couldn't just say "No sir, there isn't"? :) – TedOnTheNet Jul 19 '13 at 11:19
  • Just curious to know that Can we make it Helper.IsNull(p.contact.address.city) Wouldnt that be even more cleaner ? – Pankaj Apr 10 '14 at 10:47
  • 1
    Did King Leck get to you all ? This is the dirtiest answer I've ever seen getting this much attention. – Bitterblue Jun 24 '14 at 08:05
  • Why do you think this is a dirty solution? – simoneL Oct 03 '14 at 08:32
  • this seems kind of similar to noticing "hey, I have so much junk, but it's so bothersome to put it all under the rug all the time. I know, I could purchase a large warehouse and a square mile large rug and build a robot that automatically moves my junk under the rug in that warehouse". in the end you have to wonder, maybe you shouldn't have so much junk in the first place?? – sara Apr 07 '16 at 09:51
  • Java: ```someObject != null``` – Oliver Dixon Jun 25 '16 at 19:14
  • Can you please, provide some sample of this that works with chained ExpandoObjects ? https://stackoverflow.com/questions/46790684/is-there-a-way-to-perform-a-chained-null-check-in-a-dynamic-expando – Ewerton Oct 17 '17 at 13:13
  • variable.HasValue looks cleaner to me :) – Deepak Dec 06 '20 at 17:48
65

Your code may have bigger problems than needing to check for null references. As it stands, you are probably violating the Law of Demeter.

The Law of Demeter is one of those heuristics, like Don't Repeat Yourself, that helps you write easily maintainable code. It tells programmers not to access anything too far away from the immediate scope. For example, suppose I have this code:

public interface BusinessData {
  public decimal Money { get; set; }
}

public class BusinessCalculator : ICalculator {
  public BusinessData CalculateMoney() {
    // snip
  }
}

public BusinessController : IController {
  public void DoAnAction() {
    var businessDA = new BusinessCalculator().CalculateMoney();
    Console.WriteLine(businessDA.Money * 100d);
  }
}

The DoAnAction method violates the Law of Demeter. In one function, it accesses a BusinessCalcualtor, a BusinessData, and a decimal. This means that if any of the following changes are made, the line will have to be refactored:

  • The return type of BusinessCalculator.CalculateMoney() changes.
  • The type of BusinessData.Money changes

Considering the situation at had, these changes are rather likely to happen. If code like this is written throughout the codebase, making these changes could become very expensive. Besides that, it means that your BusinessController is coupled to both the BusinessCalculator and the BusinessData types.

One way to avoid this situation is rewritting the code like this:

public class BusinessCalculator : ICalculator {
  private BusinessData CalculateMoney() {
    // snip
  }
  public decimal CalculateCents() {
    return CalculateMoney().Money * 100d;
  }
}

public BusinessController : IController {
  public void DoAnAction() {
    Console.WriteLine(new BusinessCalculator().CalculateCents());
  }
}

Now, if you make either of the above changes, you only have to refactor one more piece of code, the BusinessCalculator.CalculateCents() method. You've also eliminated BusinessController's dependency on BusinessData.


Your code suffers from a similar issue:

interface IContact
{
    IAddress address { get; set; }
}

interface IAddress
{
    string city { get; set; }
}

class Person : IPerson
{
    public IContact contact { get; set; }
}

class Test {
  public void Main() {
    var contact = new Person().contact;
    var address = contact.address;
    var city = address.city;
    Console.WriteLine(city);
  }
}

If any of the following changes are made, you will need to refactor the main method I wrote or the null check you wrote:

  • The type of IPerson.contact changes
  • The type of IContact.address changes
  • The type of IAddress.city changes

I think you should consider a deeper refactoring of your code than simply rewriting a null check.


That said, I think that there are times where following the Law of Demeter is inappropriate. (It is, after all, a heuristic, not a hard-and-fast rule, even though it's called a "law.")

In particular, I think that if:

  1. You have some classes that represent records stored in the persistence layer of your program, AND
  2. You are extremely confident that you will not need to refactor those classes in the future,

ignoring the Law of Demeter is acceptable when dealing specifically with those classes. This is because they represent the data your application works with, so reaching from one data object into another is a way of exploring the information in your program. In my example above, the coupling caused by violating the Law of Demeter was much more severe: I was reaching all the way from a controller near the top of my stack through a business logic calculator in the middle of the stack into a data class likely in the persistence layer.

I bring this potential exception to the Law of Demeter up because with names like Person, Contact, and Address, your classes look like they might be data-layer POCOs. If that's the case, and you are extremely confident that you will never need to refactor them in the future, you might be able to get away with ignoring the Law of Demeter in your specific situation.

Kevin
  • 14,655
  • 24
  • 74
  • 124
  • 6
    Needs more upvotes, really. Compared to the accepted answer, this is far better advice imho. – Erik van Brakel Jul 17 '13 at 12:38
  • 5
    This doesn't answer the question. It tells you that the guy might not be asking the right question. But it is a great example. +1 – DidIReallyWriteThat Apr 10 '14 at 12:00
  • +1 In addition to this suggestion, it might be a good to advise use of "null" or "default" values. Rather than putting yourself in a situation where something could be set to null (or not get set at all), set that object to a value that represents a "default" state. You may be able to structure your "default" object in a way that allows it to passively reject the flow of logic, while avoiding excessive null checks or exceptions. I also reject the notion of writing IsNull() type methods. See #6 here: http://www.yacoset.com/Home/signs-that-you-re-a-bad-programmer – Thick_propheT May 06 '15 at 04:06
  • 3
    According to Uncle Bob the Law of Demeter is not applicable for data structures, like the one described in the original question. See discussion about topic here: http://stackoverflow.com/questions/26021140/law-of-demeter-with-data-model-objects – Tamas Molnar Mar 25 '16 at 13:21
48

in your case you could create a property for person

public bool HasCity
{
   get 
   { 
     return (this.Contact!=null && this.Contact.Address!= null && this.Contact.Address.City != null); 
   }     
}

but you still have to check if person is null

if (person != null && person.HasCity)
{

}

to your other question, for strings you can also check if null or empty this way:

string s = string.Empty;
if (!string.IsNullOrEmpty(s))
{
   // string is not null and not empty
}
if (!string.IsNullOrWhiteSpace(s))
{
   // string is not null, not empty and not contains only white spaces
}
Koryu
  • 1,371
  • 1
  • 11
  • 21
37

A totally different option (which I think is underused) is the null object pattern. It's hard to tell whether it makes sense in your particular situation, but it might be worth a try. In short, you will have a NullContact implementation, a NullAddress implementation and so on that you use instead of null. That way, you can get rid of most of the null checks, of course at the expense at some thought you have to put into the design of these implementations.

As Adam pointed out in his comment, this allows you to write

if (person.Contact.Address.City is NullCity)

in cases where it is really necessary. Of course, this only makes sense if city really is a non-trivial object...

Alternatively, the null object can be implemented as a singleton (e.g., look here for some practical instructions concerning the usage of the null object pattern and here for instructions concerning singletons in C#) which allows you to use classical comparison.

if (person.Contact.Address.City == NullCity.Instance)

Personally, I prefer this approach because I think it is easier to read for people not familiar with the pattern.

bigge
  • 1,488
  • 15
  • 27
  • 2
    If you want to add a little code, the resultant check might look like: `if (person.Contact.Address.City is NullCity)`. I've used this pattern in the past, although I encountered it as the [Special Case Pattern](http://martinfowler.com/eaaCatalog/specialCase.html). – Adam Houldsworth Jul 16 '13 at 09:35
  • 3
    In your example, if the `person.Contact` property is `null`, how does this answer prevent a NullReferenceException from being thrown? – Jake Berger Jul 16 '13 at 19:12
  • 4
    `person.Contact` doesn't get set to `null`, but `NullContact` - the special "null" value that has its address set to `NullAddress`, which has `NullCity`. – Jason Viers Jul 16 '13 at 21:55
26

Update 28/04/2014: Null propagation is planned for C# vNext


There are bigger problems than propagating null checks. Aim for readable code that can be understood by another developer, and although it's wordy - your example is fine.

If it is a check that is done frequently, consider encapsulating it inside the Person class as a property or method call.


That said, gratuitous Func and generics!

I would never do this, but here is another alternative:

class NullHelper
{
    public static bool ChainNotNull<TFirst, TSecond, TThird, TFourth>(TFirst item1, Func<TFirst, TSecond> getItem2, Func<TSecond, TThird> getItem3, Func<TThird, TFourth> getItem4)
    {
        if (item1 == null)
            return false;

        var item2 = getItem2(item1);

        if (item2 == null)
            return false;

        var item3 = getItem3(item2);

        if (item3 == null)
            return false;

        var item4 = getItem4(item3);

        if (item4 == null)
            return false;

        return true;
    }
}

Called:

    static void Main(string[] args)
    {
        Person person = new Person { Address = new Address { PostCode = new Postcode { Value = "" } } };

        if (NullHelper.ChainNotNull(person, p => p.Address, a => a.PostCode, p => p.Value))
        {
            Console.WriteLine("Not null");
        }
        else
        {
            Console.WriteLine("null");
        }

        Console.ReadLine();
    }
Adam Houldsworth
  • 63,413
  • 11
  • 150
  • 187
  • 11
    @newStackExchangeInstance It's the only way to get nothing done! – Adam Houldsworth Jul 16 '13 at 09:38
  • You can also have this behaviour with a two parameter's methods in order to chain as many property as you want without overload : public static TNext GetNullOrValue(this T item1, Func getNextItem) where T : class { if (item1==null) return default(TNext); return getNextItem(item1); } public static bool IsNotNull(this T item1, Func getNextItem) where T : class where TNext : class { return GetNullOrValue(item1,getNextItem) != null; } var result = person .GetNullOrValue(p => p.contact) .GetNullOrValue(c => c.address) .IsNotNull(a => a.city); – Toto Jul 16 '13 at 12:09
  • 13
    The fact that I managed to get a badge for this make me feel a little unclean. – Adam Houldsworth Jul 16 '13 at 16:06
  • 2
    For the record, I'm upvoting your answer for the paragraph above the page break. – Kevin Jul 16 '13 at 16:35
  • @kevin That makes it a little more palatable :-) – Adam Houldsworth Jul 16 '13 at 16:37
  • 1
    You must promise to use this power only for the forces of good... – Mike Loux Jul 16 '13 at 19:49
15

The second question,

I really don't like the null check being done as (something == null). Instead, is there another nice way to do something like the something.IsNull() method?

could be solved using an extension method:

public static class Extensions
{
    public static bool IsNull<T>(this T source) where T : class
    {
        return source == null;
    }
}
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
MarcinJuraszek
  • 124,003
  • 15
  • 196
  • 263
  • @MarcinJuraszek: I'm not the downvoter. Indeed a +1 voter. thanks for the cleaner extension method. Waiting for suggestions of the first question! – now he who must not be named. Jul 16 '13 at 09:27
  • 5
    Not quite relevant to the original question, but beware using extension methods like this on dynamic objects - they will fail where a simple `== null` succeeds. – jlb83 Jul 16 '13 at 13:28
  • To my sense of OOP morality, this is an abuse of extension methods, because it breaks the usual semantics of the language. If `something` is, in fact, `null`, then `something.SomeMethod()` should throw `NullReferenceException`. – Andrew Palmer Jul 03 '16 at 23:42
10

If for some reason you don't mind going with one of the more 'over the top' solutions, you might want to check out the solution described in my blog post. It uses the expression tree to find out whether the value is null before evaluating the expression. But to keep performance acceptable, it creates and caches IL code.

The solution allows you do write this:

string city = person.NullSafeGet(n => n.Contact.Address.City);
Sandor Drieënhuizen
  • 6,310
  • 5
  • 37
  • 80
8

You can write:

public static class Extensions
    {
        public static bool IsNull(this object obj)
        {
            return obj == null;
        }
    }

and then:

string s = null;
if(s.IsNull())
{

}

Sometimes this makes sense. But personally I would avoid such things... because this is is not clear why you can call a method of the object that is actually null.

Vladimir Gondarev
  • 1,243
  • 7
  • 14
5

Do it in a separate method like:

private test()
{
    var person = new Person();
    if (!IsNull(person))
    {
        // Proceed
              ........

Where your IsNull method is

public bool IsNull(Person person)
{
    if(Person != null && 
       Person.Contact != null && 
       Person.Contact.Address != null && 
       Person.Contact.Address.City != null)
          return false;
    return true;
}
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Ashok Damani
  • 3,896
  • 4
  • 30
  • 48
  • 2
    Thanks for the method. But, i don't really want to do a if(Person != null && Person.Contact!=null && Person.Contact.Address!= null && Person.Contact.Address.City != null) return false; – now he who must not be named. Jul 16 '13 at 09:24
4

Do you need C#, or do you only want .NET? If you can mix another .NET language, have a look at Oxygene. It's an amazing, very modern OO language that targets .NET (and also Java and Cocoa as well. Yep. All natively, it really is quite an amazing toolchain.)

Oxygene has a colon operator which does exactly what you ask. To quote from their miscellaneous language features page:

The Colon (":") Operator

In Oxygene, like in many of the languages it was influenced by, the "." operator is used to call members on a class or object, such as

var x := y.SomeProperty;

This "dereferences" the object contained in "y", calls (in this case) the property getter and returns its value. If "y" happens to be unassigned (i.e. "nil"), an exception is thrown.

The ":" operator works in much the same way, but instead of throwing an exception on an unassigned object, the result will simply be nil. For developers coming from Objective-C, this will be familiar, as that is how Objective-C method calls using the [] syntax work, too.

... (snip)

Where ":" really shines is when accessing properties in a chain, where any element might be nil. For example, the following code:

var y := MyForm:OkButton:Caption:Length;

will run without error, and return nil if any of the objects in the chain are nil — the form, the button or its caption.

matt
  • 333
  • 2
  • 10
  • 23
David
  • 13,360
  • 7
  • 66
  • 130
  • What will be the result type of y then? Nullable int/long? – Peter Lillevold Jul 16 '13 at 12:15
  • Looks like. This is kind of neat; it's kind of an "IronDelphi" in its .NET form. Probably won't be picking it up any time soon, but worth a look. – KeithS Jul 16 '13 at 14:38
  • Either a reference or a nullable type. From [the documentation on the colon operator](http://wiki.oxygenelanguage.com/en/Colon_Operator): "The result of the colon operator is always a reference or a nullable type. .... If the result of the member is a value type (such as an Int32), the result will be changed into a nullable of that value type (e.g. a nullable Int32)." – David Jul 23 '13 at 09:00
  • +1 for bringing Oxygene into view. Never heard it before. I intended to search recently for new programming languages compatible with .NET. – Miroslav Popov Aug 01 '13 at 23:05
3
try
{
  // do some stuff here
}
catch (NullReferenceException e)
{
}

Don't actually do this. Do the null checks, and figure out what formatting you can best live with.

jwg
  • 5,547
  • 3
  • 43
  • 57
3

I have an extension that could be useful for this; ValueOrDefault(). It accepts a lambda statement and evaluates it, returning either the evaluated value or a default value if any expected exceptions (NRE or IOE) are thrown.

    /// <summary>
    /// Provides a null-safe member accessor that will return either the result of the lambda or the specified default value.
    /// </summary>
    /// <typeparam name="TIn">The type of the in.</typeparam>
    /// <typeparam name="TOut">The type of the out.</typeparam>
    /// <param name="input">The input.</param>
    /// <param name="projection">A lambda specifying the value to produce.</param>
    /// <param name="defaultValue">The default value to use if the projection or any parent is null.</param>
    /// <returns>the result of the lambda, or the specified default value if any reference in the lambda is null.</returns>
    public static TOut ValueOrDefault<TIn, TOut>(this TIn input, Func<TIn, TOut> projection, TOut defaultValue)
    {
        try
        {
            var result = projection(input);
            if (result == null) result = defaultValue;
            return result;
        }
        catch (NullReferenceException) //most reference types throw this on a null instance
        {
            return defaultValue;
        }
        catch (InvalidOperationException) //Nullable<T> throws this when accessing Value
        {
            return defaultValue;
        }
    }

    /// <summary>
    /// Provides a null-safe member accessor that will return either the result of the lambda or the default value for the type.
    /// </summary>
    /// <typeparam name="TIn">The type of the in.</typeparam>
    /// <typeparam name="TOut">The type of the out.</typeparam>
    /// <param name="input">The input.</param>
    /// <param name="projection">A lambda specifying the value to produce.</param>
    /// <returns>the result of the lambda, or default(TOut) if any reference in the lambda is null.</returns>
    public static TOut ValueOrDefault<TIn, TOut>(this TIn input, Func<TIn, TOut> projection)
    {
        return input.ValueOrDefault(projection, default(TOut));
    }

The overload not taking a specific default value will return null for any reference type. This should work in your scenario:

class test
{
    private test()
    {
        var person = new Person();
        if (person.ValueOrDefault(p=>p.contact.address.city) != null)
        {
            //the above will return null without exception if any member in the chain is null
        }
    }
}
KeithS
  • 70,210
  • 21
  • 112
  • 164
  • I'm not the downvoter, but I'll just comment. This would be an awesome way of using extension methods, except it might put people in the wrong mindset; ie "you can 'sometimes' call a method on null". If I were programming a project alone I might use it, but usually the point of extension methods is that they're nearly imperceptible from their cousin local-methods. (ie, adding toUpperCase to a string object that only has a toLowerCase method). It does work though, and very much like Ruby's isNull. – Katana314 Jul 16 '13 at 17:24
  • Ironically, my comment was very similar to your criticism of my use of struct's, since they often appear interchangable with classes! Whatever - maybe we should just use all the tricks of the language, and when it confuses newbies, call it job security. – Katana314 Jul 16 '13 at 17:25
3

Such a reference chain may occurre for example if you use an ORM tool, and want to keep your classes as pure as possible. In this scenario I think it cannot be avoided nicely.

I have the following extension method "family", which checks if the object on which it's called is null, and if not, returns one of it's requested properties, or executes some methods with it. This works of course only for reference types, that's why I have the corresponding generic constraint.

public static TRet NullOr<T, TRet>(this T obj, Func<T, TRet> getter) where T : class
{
    return obj != null ? getter(obj) : default(TRet);
}

public static void NullOrDo<T>(this T obj, Action<T> action) where T : class
{
    if (obj != null)
        action(obj);
}

These methods add almost no overhead compared to the manual solution (no reflection, no expression trees), and you can achieve a nicer syntax with them (IMO).

var city = person.NullOr(e => e.Contact).NullOr(e => e.Address).NullOr(e => e.City);
if (city != null)
    // do something...

Or with methods:

person.NullOrDo(p => p.GoToWork());

However, one could definetely argue about the length of code didn't change too much.

Zoltán Tamási
  • 12,249
  • 8
  • 65
  • 93
2

In my opinion, the equality operator is not a safer and better way for reference equality.

It's always better to use ReferenceEquals(obj, null). This will always work. On the other hand, the equality operator (==) could be overloaded and might be checking if the values are equal instead of the references, so I will say ReferenceEquals() is a safer and better way.

class MyClass {
   static void Main() {
      object o = null;
      object p = null;
      object q = new Object();

      Console.WriteLine(Object.ReferenceEquals(o, p));
      p = q;
      Console.WriteLine(Object.ReferenceEquals(p, q));
      Console.WriteLine(Object.ReferenceEquals(o, p));
   }
}

Reference: MSDN article Object.ReferenceEquals Method.

But also here are my thoughts for null values

  • Generally, returning null values is the best idea if anyone is trying to indicate that there is no data.

  • If the object is not null, but empty, it implies that data has been returned, whereas returning null clearly indicates that nothing has been returned.

  • Also IMO, if you will return null, it will result in a null exception if you attempt to access members in the object, which can be useful for highlighting buggy code.

In C#, there are two different kinds of equality:

  • reference equality and
  • value equality.

When a type is immutable, overloading operator == to compare value equality instead of reference equality can be useful.

Overriding operator == in non-immutable types is not recommended.

Refer to the MSDN article Guidelines for Overloading Equals() and Operator == (C# Programming Guide) for more details.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Rajeev Bera
  • 2,021
  • 1
  • 16
  • 30
  • If the equality operator does not have null handling I will stop using that library immediately. – It'sNotALie. Jul 16 '13 at 09:37
  • In C#, there are two different kinds of equality: reference equality and value equality. and I am making point that for reference equality equality operator is not best :) – Rajeev Bera Jul 16 '13 at 09:54
  • @newStackExchangeInstance - Overriding operator == in non-immutable types is not recommended, Please read the MSDN link posted in my answer – Rajeev Bera Jul 16 '13 at 09:59
  • I know. In both of those equalities, null is not equal to anything but null. If that isn't how == works for that type, then that operator is really badly written. – It'sNotALie. Jul 16 '13 at 10:10
1

As much as I love C#, this is one thing that's kind of likable about C++ when working directly with object instances; some declarations simply cannot be null, so there's no need to check for null.

The best way you can get a slice of this pie in C# (which might be a bit too much redesigning on your part - in which case, take your pick of the other answers) is with struct's. While you could find yourself in a situation where a struct has uninstantiated "default" values (ie, 0, 0.0, null string) there's never a need to check "if (myStruct == null)".

I wouldn't switch over to them without understanding their use, of course. They tend to be used for value types, and not really for large blocks of data - anytime you assign a struct from one variable to another, you tend to be actually copying the data across, essentially creating a copy of each of the original's values (you can avoid this with the ref keyword - again, read up on it rather than just using it). Still, it may fit for things like StreetAddress - I certainly wouldn't lazily use it on anything I didn't want to null-check.

Katana314
  • 8,429
  • 2
  • 28
  • 36
  • 1
    No. Just no. `structs` are to be used for *immutable* complex types. You get yourself in a lot of hot water very quickly by making a mutable struct to solve a problem like this. On top of that, strings aren't structs; they're reference types, and they can be null, so even in simple cases you have to check for null. – KeithS Jul 16 '13 at 14:31
  • Who ever said strings were structs? I said right in my second paragraph you could have a null string inside of one. Furthermore, there are definitely scenarios, for instance in game development, where you wouldn't want to be using them in an immutable way. You just need to be aware that you are maintaining a singular instance in one particular spot, and perhaps passing references; that's something C/C++ developers have to be aware of all the time. – Katana314 Jul 16 '13 at 14:38
  • That is not the way you use structs in C#. It causes behaviors such as "value reversion" that the average developer would not expect from a mutable type (however common it is among its C-family brethren), and encouraging both mutable structs and mutable classes often leads to combinations, where some of the object graph's state can change when it's passed into a method, while others won't. For these reason nearly every authority on C# says to make your structs immutable. – KeithS Jul 16 '13 at 14:47
  • Even some reference types are implemented in an immutable way by the language and framework. Strings for example; they look and act mutable, but every unique string ever created by a program is created as a new string with a new heap location. Among other things, this prevents reference-type behavior when using strings in structs that cross method calls; the string can change in the struct all you want on the other side of a method call, but upon return the original string the struct had is still on the heap, referenced by the copy of the struct. – KeithS Jul 16 '13 at 14:51
  • The main difficulty on this one is developer confusion if it's used the wrong way, ie passing the struct `Address`, alone, into a seperate method that modifies it. The thing that annoys me, though, is that there are *dozens* of behaviors one should avoid in C# lest they lead to confusing issues later. In a world where I could be sure my whole team knows what ValueTypes are, how they work, and when not to use them, I wouldn't be too concerned about following the pattern to define something as "not null" though. – Katana314 Jul 16 '13 at 14:56
1

Depending on what the purpose of using the "city" variable is, a cleaner way could be to separate the null checks into different classes. That way you also wouldn't be violating the Law of Demeter. So instead of:

if (person != null && person.contact != null && person.contact.address != null && person.contact.address.city != null)
{ 
    // do some stuff here..
}

You'd have:

class test
{
    private test()
    {
        var person = new Person();
        if (person != null)
        {
            person.doSomething();
        }
    }
}

...

/* Person class */
doSomething() 
{
    if (contact != null)
    {
        contact.doSomething();
    }
}

...

/* Contact class */
doSomething()
{
    if (address != null) 
    {
        address.doSomething();
    }
}

...

/* Address class */
doSomething()
{
    if (city != null)
    {
        // do something with city
    }
}

Again, it depends on the purpose of the program.

Thomas
  • 1,103
  • 3
  • 13
  • 25
1

In what circumstances can those things be null? If nulls would indicate a bug in the code then you could use code contracts. They will pick it up if you get nulls during testing, then will go away in the production version. Something like this:

using System.Diagnostics.Contracts;

[ContractClass(typeof(IContactContract))]
interface IContact
{
    IAddress address { get; set; }
}

[ContractClassFor(typeof(IContact))]
internal abstract class IContactContract: IContact
{
    IAddress address
    {
        get
        {
            Contract.Ensures(Contract.Result<IAddress>() != null);
            return default(IAddress); // dummy return
        }
    }
}

[ContractClass(typeof(IAddressContract))]
interface IAddress
{
    string city { get; set; }
}

[ContractClassFor(typeof(IAddress))]
internal abstract class IAddressContract: IAddress
{
    string city
    {
        get
        {
            Contract.Ensures(Contract.Result<string>() != null);
            return default(string); // dummy return
        }
    }
}

class Person
{
    [ContractInvariantMethod]
    protected void ObjectInvariant()
    {
        Contract.Invariant(contact != null);
    }
    public IContact contact { get; set; }
}

class test
{
    private test()
    {
        var person = new Person();
        Contract.Assert(person != null);
        if (person.contact.address.city != null)
        {
            // If you get here, person cannot be null, person.contact cannot be null
            // person.contact.address cannot be null and person.contact.address.city     cannot be null. 
        }
    }
}

Of course, if the possible nulls are coming from somewhere else then you'll need to have already conditioned the data. And if any of the nulls are valid then you shouldn't make non-null a part of the contract, you need to test for them and handle them appropriately.

digitig
  • 1,989
  • 3
  • 25
  • 45
0

One way to remove null checks in methods is to encapsulate their functionality elsewhere. One way to do this is through getters and setters. For instance, instead of doing this:

class Person : IPerson
{
    public IContact contact { get; set; }
}

Do this:

class Person : IPerson
{
    public IContact contact 
    { 
        get
        {
            // This initializes the property if it is null. 
            // That way, anytime you access the property "contact" in your code, 
            // it will check to see if it is null and initialize if needed.
            if(_contact == null)
            {
                _contact = new Contact();
            }
            return _contact;
        } 
        set
        {
            _contact = value;
        } 
    }
    private IContact _contact;
}

Then, whenever you call "person.contact", the code in the "get" method will run, thus initializing the value if it is null.

You could apply this exact same methodology to all of the properties that could be null across all of your types. The benefits to this approach are that it 1) prevents you from having to do null checks in-line and it 2) makes your code more readable and less prone to copy-paste errors.

It should be noted, however, that if you find yourself in a situation where you need to perform some action if one of the properties is null (i.e. does a Person with a null Contact actually mean something in your domain?), then this approach will be a hindrance rather than a help. However, if the properties in question should never be null, then this approach will give you a very clean way of representing that fact.

--jtlovetteiii

jtlovetteiii
  • 285
  • 1
  • 3
  • 8
0

You could use reflection, to avoid forcing implementation of interfaces and extra code in every class. Simply a Helper class with static method(s). This might not be the most efficient way, be gentle with me, I'm a virgin (read, noob)..

public class Helper
{
    public static bool IsNull(object o, params string[] prop)
    {
        if (o == null)
            return true;

        var v = o;
        foreach (string s in prop)
        {
            PropertyInfo pi = v.GetType().GetProperty(s); //Set flags if not only public props
            v = (pi != null)? pi.GetValue(v, null) : null;
            if (v == null)
                return true;                                
        }

        return false;
    }
}

    //In use
    isNull = Helper.IsNull(p, "ContactPerson", "TheCity");

Offcourse if you have a typo in the propnames, the result will be wrong (most likely)..

TDull
  • 753
  • 5
  • 12