Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Handling C# Properties that shouldn't be null

Tags:

c#

properties

When setting up some reference type properties for a project I'm working on, I came accross a few properties that needed to be properly initialized to be used and should never be null. I've seen a few ways to handle this and can't really determine if there are any major drawbacks to any of the primary ways I've seen to handle this. I'd like to get the community's opinion about the best way to handle this and what the potential drawbacks to each method might be.

Given a simple class, I've seen several ways to handle making sure a property never has a null version of this class in a property

public class MyClass
{
  //Some collection of code
}

Option 1 - Initialize the backing store

public class OtherClass1
    {
        private MyClass _mC = new MyClass();
        public MyClass MC
        {
            get { return _mC; }
            set { _mC = value; }
        }
    }

Option 2 - Initialize the property in the constructor

public class OtherClass2
    {
        public MyClass MC { get; set; }     

        public OtherClass2()
        {
            MC = new MyClass(); 
        }
    }

Option 3 - Handle initialization as needed in the Getter

public class OtherClass3
    {
        private MyClass _mC;
        public MyClass MC
        {
            get
            {
                if (_mC == null)
                    _mC = new MyClass();
                return _mC; 
            }
            set { _mC = value; }
        }
    }

I'm sure there are other ways, but these are the ones that come to mind and I have seen. I'm mostly trying to determine if there's a well established best practice on this or if there's a specific concern with any of the above.

Cheers,

Steve

like image 493
Steve Brouillard Avatar asked Mar 06 '09 16:03

Steve Brouillard


3 Answers

Best option unless you really can get away with just creating a new instance yourself: only provide constructors which take all the required values, and validate them at that point.

like image 198
Jon Skeet Avatar answered Nov 15 '22 18:11

Jon Skeet


As far as I know, there is not an established best practice here for a simple reason: each of your options has a different performance/memory footprint profile. The first option is appropriate for a reference to an object that you know must be instantiated in a class that you are sure will be used. Honestly, though, I never take this approach because I think that #2 is just more appropriate; just a sense that this is what a constructor is for.

The last option is appropriate when you are not sure whether an option will be used. It permits you take up the resource only as needed.

BTW, this question is right "next door" to a number of other issues such as the appropriate use of the Singleton pattern, the use of abstract classes or interfaces for your deferred object, etc. that might be useful for you to explore to gain greater insight.

Update: It strikes me that there is at least one case where initializing an instance in the class definition is appropriate (your Option #1). If the instance will be static then this is the only appropriate place to initialize it:

private static readonly DateTime firstClassDate = DateTime.Parse("1/1/2009 09:00:00 AM");

I thought of this when creating the above line of code in some Unit tests I was writing today (the readonly being optional wrt my point but appropriate in my case).

like image 45
Mark Brittingham Avatar answered Nov 15 '22 18:11

Mark Brittingham


Paraphrasing a question I posted a few days ago but I think it may be helpful to enforce code rules and make sure that Nulls a re not used where you don't want them:

Microsoft just released Code Contracts, a tool that integrates with Visual Studio and allows you to define contracts for your .Net code and get runtime and compile time checking.

Watch the video on Channel 9 that shows how it being used.

For now it's an add-on but it will be part of the Base Class Library in .Net 4.0

like image 33
Renaud Bompuis Avatar answered Nov 15 '22 18:11

Renaud Bompuis