Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the difference between assigning null to an instance of a class and just declaration

I'm trying to understand if there is any difference between assigning null to an instance of a class and just declaring the class.

For an example, I have a class:

public class MyClass
{
    public string FirstProperty { get; set; }
    public int SecondProperty { get; set; }
}

I declare two instances of the class:

MyClass Instance1 = null;
MyClass Instance2;  // just declaration

Is there any difference between Instance1 and Instance2?

If yes, is it safe? Is it a good habit to use the 'delcaration only' style (as is the case with Instance2 in the example above)?

like image 978
Serge Voloshenko Avatar asked Jan 27 '17 16:01

Serge Voloshenko


1 Answers

Then I'm creating two instances of the class:

You're not creating any instances. You're creating two places to put instances if they are ever created. The first you've explicitly said does not have an instance, they second just doesn't have one.

Is there any difference between Instance1 and Instance2?

It depends on where you've done that.

If that code is within a class or struct then you've created two fields, both of which will be set to null initially, unless a constructor does something else.

If you've that code within a method (including a constructor or property accessor) then you've got two local variables (though the convention would be to use lower-case here).

The first has been set to null and you can do things with it that are valid to do with null (pass it to a method [though it may throw an exception if it refuses to accept null) compare it with something to confirm that it is indeed null or isn't indeed the same as something that really does have an instance.

The second has not been assigned and therefore it is illegal to do anything other than assign it something (whether null, or an instance). Any attempt to do anything before it's definitely been set will be a compiler error. E.g.:

MyClass Instance2;
if (valueThatJustHappensToAlwaysBeTrue)
{
   Instance2 = new MyClass();
}
bool isNull = Instance2 == null; // Error! Not guaranteed to be assigned strongly enough for the compiler to know.

Is yes, is it safe and it's a good habit to have Instance2 with declaration only?

When possible, it's a good habit to be declaring as close to the first assignment (the initialisation) as possible, ideally at the same time:

MyClass instance = new MyClass();

However, if you've a few different possible paths, such as:

MyClass instance;
if (boolValue)
{
   instance = new MyClass(1); // Yes, I know there's no int-taking ctor on your class, but it defeats the argument when the bare constructor is the only one available, so let's say there is.
}
else if (otherBoolValue)
{
   throw new SomeException();
}
else if (someIntValue > 42)
{
   instance = new MyClass(3);
}
else
{
   instance = new MyClass(9);
}

Now, it's impossible to get to the end of this chain with an uninitialised instance. Either it will have been set, or the exception will have been thrown. If we'd thought it might be "safer" to start with MyClass instance = null then we'd have perhaps hidden a mistake. The logic above is meant to assign it something for every path and because of the rule that you can't use an instance that isn't guaranteed to be assigned then a mistake in that would cause a compiler error, and the mistake would be obvious. If it's assigned to a "placeholder" null to begin with such a mistake isn't going to be quite as immediately obvious, and could cause a bug.

So in cases like bare declaration is better.

But that said, complicated logic is always better avoided when possible, so those sort of convoluted chains should be rare. In other cases the style of declaring and assigning at the same point means you've no gap between the two where a mistake can slip in.

like image 166
Jon Hanna Avatar answered Oct 01 '22 03:10

Jon Hanna