Почему использование (ноль) допустимого регистра в C #? - PullRequest
10 голосов
/ 04 марта 2011

Может кто-нибудь объяснить мне, почему приведенный ниже код действителен в C # и выполняет вызов Console.WriteLine?

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

Он компилируется в (в конце показан блок).Как видите, компилятор решает не выполнять метод Dispose() и переходит к инструкции endfinally.

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

Однако, если я запускаю следующий код, произойдет сбой с NullReferenceException (что ожидается):

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

Почему компилируется первая версия?Почему компилятор решает не выполнять Dispose()?Есть ли другие случаи, когда компилятор может решить не вызывать Dispose() в блоке using?

Ответы [ 3 ]

12 голосов
/ 04 марта 2011

Спецификация языка прямо заявляет (8.13), что захваченное значение при необходимости проверяется на нулевое значение, т. Е. finally по существу (с предостережениями вокруг ненулевых типов)

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

Я часто используюэто в моих интересах, для вещей, которые могут быть нулевыми, но когда это не так: нужно избавляться.Фактически, вот полезный сценарий (вручную перечисляя IEnumerable):

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

, поскольку неуниверсальная версия IEnumerator не обязательно IDisposable, но когда она есть, должна быть удалена.

1 голос
/ 04 марта 2011

Я думаю, что это естественный результат более общего случая using(some_expression), где some_expression разрешено оценивать как null.

Потребовалось бы специальное правило, чтобы отличить этот случай от более общего.

0 голосов
/ 04 марта 2011

Будет игнорироваться, если объект нулевой - http://msdn.microsoft.com/en-us/library/yh598w02.aspx

...