Click here to Skip to main content
16,018,938 members
Articles / All Topics

A Lot About Nothing (or null)

Rate me:
Please Sign up or sign in to vote.
4.57/5 (6 votes)
17 Mar 2010CPOL2 min read 14.3K   3   7
A lot about nothing (or null)

Introduction

I believe that the code you write should express your intended functionality in a manner that reads almost like a story. To achieve this, you need to use a coding style that includes descriptive names for methods, properties, and fields. One area that a lot of people don’t consider is what their code says when they use null in C# or Nothing in VB. Used incorrectly, it can result in confusing code and subtle errors.

So let's start our null using code to English translator and examine some code idioms.

Initializing a Variable to null

This is the simplest of statements:

C#
ISpoon aSpoon = null;

This means “I’m probably going to use a spoon at some point in this class or method, but I haven't decided which one, haven’t been given one, or haven’t made one yet.” Another way of say this is “There is no spoon”.

Notice that the variable was defined in terms of the interface ISpoon. The reason for this is that there are many different types of spoon (silver, coffee, sugar, serving, wooden, …) and I want to be able to use the most appropriate for a given situation.

Assigning null to a Variable

Take the following code:

C#
ISpoon aSpoon = GetAWoodenSpoonFromTheDrawer();

theCook.StirsSauceWith(aSpoon);
aSpoon = null;

In this situation, you have gotten a spoon and used it. The assignment says “I’m done with this spoon and don’t care about it anymore. I’ll just drop it wherever, and the cleanup crew (the garbage collector in .NET) will pick it up, wash it, and put it back where someone else can use it”.

Returning null from a Method

Methods will typically return either a single value or a collection of values. For the single value returning method, returning null will mean something different depending on the intent of the method. For example,

C#
ISpoon aSpoon = GetAWoodenSpoonFromTheDrawer();

would mean to me that there wasn’t a wooden spoon in the drawer. Now you will have to check that aSpoon is not null before using it and chose a different type of spoon, or get a wooden spoon elsewhere. Personally, I find this type of code detracts from the flow of the code’s story and prefer to throw an exception as the exception can tell you what went wrong. So instead of:

C#
ISpoon aSpoon = GetAWoodenSpoonFromTheDrawer();

// couldn't get a spoon from the drawer
if (aSpoon == null)
    aSpoon = FindAWoodenSpoonElsewhere();

// use the spoon if one was found.
if (aSpoon != null)
{
    ...
}

I would write:

C#
ISpoon aSpoon = null;
try
{
    ISpoon aSpoon = GetAWoodenSpoonFromTheDrawer();
}
// there isn't a spoon in the drawer
catch (NoSpoonFoundException)
{
    // look elsewhere
    try
    {
        aSpoon = FindAWoodenSpoonElsewhere();
    }
    // No spoon found anywhere
    catch(NoSpoonFoundException)
    {
        aSpoon = BuyAWoodenSpoon();
    }
}
// there was a spoon, but it was dirty
catch(DirtySpoonException)

{
    WashDishes();
    aSpoon = GetAWoodenSpoonFromTheDrawer();
} 

// use the spoon if one was found.
if (aSpoon != null)
{
...
}

For the case where the method returns a collection of items, as in:

C#
ICollection<ISpoon> mySilverSpoons = GetAllSpoonsThatAre("silver");

returning a null does not say “There are no spoons”. Rather, it says “I couldn’t create a collection of spoons”. In this case, I would return a collection with no items. As before, errors should throw exceptions. This means that you can safely iterate the collection returned. The usage pattern would look like:

C#
try
{
    ICollection<ISpoon> mySilverSpoons = GetAllSpoonsThatAre("silver");

    foreach(var spoon in mySilverSpoons)
    {
        Polish(spoon);
    }
}
catch(MissingSilverwareBoxException)
{
    CallPolice();
}
catch(NoPolishAvailable)
{
    Order("Polish");
    Reschedule("Polish Silver Task");
}

Due to time constraints, I’m not going to address null parameters in this blog.

I hope this has given you something to think about when architecting/designing you applications. Just remember Nothing (or null) can hurt you if you don’t think about Nothing.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior) CodeProject
Canada Canada
As Senior Architect, Matthew is responsible for the Architecture, Design, and Coding of the CodeProject software as well as Manager of the Infrastructure that runs the web site.

Matthew works on improving the performance and experience of the Code Project site for users, clients, and administrators.

Matthew has more years of software development, QA and architecture experience under his belt than he likes to admit. He graduated from the University of Waterloo with a B.Sc. in Electrical Engineering. He started out developing micro-processor based hardware and software including compilers and operating systems.
His current focus is on .NET web development including jQuery, Webforms, MVC, AJAX, and patterns and practices for creating better websites.
He is the author of the Munq IOC, the fastest ASP.NET focused IOC Container.
His non-programming passions include golf, pool, curling, reading and building stuff for the house.

Comments and Discussions

 
GeneralNot really Pin
DaProgramma23-Mar-10 1:41
DaProgramma23-Mar-10 1:41 
GeneralRe: Not really Pin
Matthew Dennis23-Mar-10 7:10
sysadminMatthew Dennis23-Mar-10 7:10 
GeneralRe: Not really Pin
DaProgramma23-Mar-10 8:18
DaProgramma23-Mar-10 8:18 
Matthew Dennis wrote:

For your example, returning null says, "There is no person by that name". However, depending on the collection/repository implementation you might get a KeyNotFoundException which you might want to handle, just to be safe.


No.

If not finding a name is a valid outcome for a lookup function, letting out a KeyNotFoundException would definitely be an error. Using a container that throws if something is not found would be a reason for some talk between that programmer and me.

Another thing is that such (programming) errors do happen. But the caller should never cope for that errors - they should silently bubble up to some central top level control function (mostly the message loop) where such logic errors should be handled.

Take some time and think about it:

- if a situation is to be expected, using exceptions is not the right way to model that.

- for "unexpected" things (mostly logic errors), exceptions are the language means to use. BUT: mostly it makes no sense to handle them one level up. - most of the time it is best to handle them very top level.

When I saw someone handling exceptions deeply in the code, it mostly was bad design.


You might also get other exceptions due to database errors, timeouts, business rule violations, etc.

Definitely. But this thread is about nulls as return values, not the usability of exceptions.


Greetz
daProgramma
GeneralSpoon-power! Pin
CurtainDog22-Mar-10 22:26
CurtainDog22-Mar-10 22:26 
GeneralRe: Spoon-power! Pin
Matthew Dennis23-Mar-10 7:03
sysadminMatthew Dennis23-Mar-10 7:03 
GeneralI don't agree with using try catch Pin
Micke D22-Mar-10 13:33
Micke D22-Mar-10 13:33 
GeneralRe: I don't agree with using try catch Pin
Matthew Dennis22-Mar-10 14:55
sysadminMatthew Dennis22-Mar-10 14:55 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.