43

With a piece of code like this, the compiler complains on c.MyProperty:

MyClass c;

try { throw new Exception(); }
catch (Exception) { }

c.MyProperty = 2; // "Use of unassigned local variable 'c'".

Yet it doesn't complain if you assign a null to c in initialization:

MyClass c = null;

try { throw new Exception(); }
catch (Exception) { }

c.MyProperty = 2; // no complains this time.

So, why does this work? If c wasn't assigned a null and the compiler hypothetically allowed it, wouldn't the same exception be thrown at c.MyProperty, Object reference not set to an instance of an object?

Andreas Grech
  • 105,982
  • 98
  • 297
  • 360
  • Hmm, that is interesting, my guess would be though that this code (second version) would still throw an exception at Runtime.. it's likely just a visual studio issue that is not picking up the null assignment - Just a guess ? – Dave Long Jun 02 '11 at 10:13
  • 1
    Take a look to http://stackoverflow.com/questions/4770426/non-initialized-vs-null-values-of-reference-types – Haplo Jun 02 '11 at 10:17

4 Answers4

84

When you assign null to the variable you're telling the compiler to back off because you know better than him so he should not complain about this.

This is probably due to the fact that assigning null is considered to imply an explicit action by the developer.

João Angelo
  • 56,552
  • 12
  • 145
  • 147
  • 5
    Although that made me laugh, I'm still not closer to an answer. – Andreas Grech Jun 02 '11 at 10:13
  • 26
    @Andreas: This is the actual answer, this is why it is allowed. C# will let you **intentionally** shoot your self in the foot. It just won't let you do it _unintentionally_. – Binary Worrier Jun 02 '11 at 10:17
  • 2
    Although the way I answered was meant to add some humor to my opinion, I genuinely think that this can be why the compiler stops complaining so it's a valid answer even if it at the days end is not the correct one. – João Angelo Jun 02 '11 at 10:18
  • 3
    I always thought compilers were she's. – m12lrpv Aug 19 '19 at 02:24
3

This is because the C# Language specification v. 4.0 section 1.6.6.2 "Method body and local variables" states the following:

A method body can declare variables that are specific to the invocation of the method. Such variables are called local variables.

[skipped]

C# requires a local variable to be definitely assigned before its value can be obtained.

This is to avoid letting you to shoot yourself in the foot, as Binary Worrier neatly pointed out.

Community
  • 1
  • 1
Igor Korkhov
  • 8,283
  • 1
  • 26
  • 31
1

The reason for this exception is that you've not assigned a default value for the variable e.g

if (Request.Files != null  && Request.Files.Count > 0)
            {
                 Image = Request.Files.AllKeys[0];
            }
var stream  = new FileStream(Image,FileMode.Open);

now the Image variable will give compiler error

Use of unassigned local variable 'Image'

That is due to the reason that there is possibility that condition becomes true and control will never get to know what the Image variable is . so either place an else block or assign a default value as below.

string Image = "";
if (Request.Files != null  && Request.Files.Count > 0)
            {
                 Image = Request.Files.AllKeys[0];
            }
var stream  = new FileStream(Image,FileMode.Open);
Mani
  • 2,391
  • 5
  • 37
  • 81
1

Think of it this way, the compiler is not telling you that it is going to throw a null reference and therefore it can't compile, but rather that one of the conditions aren't met that are required to compile, i.e. that it has to be definitely assigned.

According to the spec null is a c# literal: "The null-literal can be implicitly converted to a reference type or nullable type"

As well as in terms of assignments: (taken from the spec)

Start of quote taken from the spec

5.3.3 Precise rules for determining definite assignment In order to determine that each used variable is definitely assigned, the compiler must use a process that is equivalent to the one described in this section.

The compiler processes the body of each function member that has one or more initially unassigned variables. For each initially unassigned variable v, the compiler determines a definite assignment state for v at each of the following points in the function member:

· At the beginning of each statement

· At the end point (§8.1) of each statement

· On each arc which transfers control to another statement or to the end point of a statement

· At the beginning of each expression

· At the end of each expression

End of quote

So even though null is not actually pointing to an object in memory, it does fulfill the requirements of being definitely assigned and that is why the compiler allows it.

TBohnen.jnr
  • 5,117
  • 1
  • 19
  • 26