Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is using(null) a valid case in C#?

Could someone please explain to me why the code shown below is valid in C# and executes the call to Console.WriteLine?

using (null) 
{
   Console.WriteLine ("something is here")
}

It compiles into (finally block is shown). As you can see compiler decides not to execute the Dispose() method and jumps to the endfinally instruction.

IL_0013:  ldnull
IL_0014:  ceq
IL_0016:  stloc.1
IL_0017:  ldloc.1
IL_0018:  brtrue.s   IL_0021 // branches here and decide not to execute Dispose()
IL_001a:  ldnull
IL_001b:  callvirt   instance void [mscorlib]System.IDisposable::Dispose()
IL_0020:  nop
IL_0021:  endfinally

However, if I run the following code, it will fail with a NullReferenceException (which is expected):

((IDisposable)null).Dispose();
IL_0023:  ldnull
IL_0024:  callvirt   instance void [mscorlib]System.IDisposable::Dispose()

Why does the first version compile? Why does the compiler decide not to execute Dispose()? Are there any other cases when compiler may decide not to call Dispose() in a using block?

like image 235
Andrey Taptunov Avatar asked Mar 04 '11 08:03

Andrey Taptunov


People also ask

IS null statement a valid statement in C?

The null statement satisfies the syntax requirement in cases that do not need a substantive statement body. As with any other C statement, you can include a label before a null statement.

Why do we use null in C?

The C NULL is a special reserved pointer value that does not point to any valid data object. The SQL null value is a special value that is distinct from all non-null values and denotes the absence of a (non-null) value.

IS null considered false in C?

Yes. NULL evaluates to false, since C considers any non-zero value true and any zero value false. NULL is essentially the zero address and is treated as such in comparisons, and I believe would be promoted to an int for the boolean check.

Why is null necessary?

NULL values are used to indicate that you could have a value, but you don't know what that value should be yet. They are placeholders until you finally collect the data needed to fill the table field with a real value. You should never confuse NULL values for zeros or blank strings. This is another misconception.


1 Answers

The language spec explicitly states (8.13) that the captured value is tested for null if necessary, i.e. the finally is essentially (with caveats around non-nullable types)

if(tmp != null) tmp.Dispose();

I frequently use this to my advantage, for things that might be null, but when they aren't: need disposing. In fact, here's a useful scenario (manually enumerating IEnumerable):

IEnumerable blah = ...; // note non-generic version
IEnumerator iter = blah.GetEnumerator();
using(iter as IDisposable)
{
    // loop
}

as the non-generic version of IEnumerator isn't necessarily IDisposable, but when it is, should be disposed.

like image 177
Marc Gravell Avatar answered Oct 12 '22 09:10

Marc Gravell