CA2000 для метода, использующего «using», но не использующего try / finally - PullRequest
3 голосов
/ 16 марта 2012

У меня странная ситуация, которую я пытаюсь понять. Этот фрагмент кода дает CA2000 (вызовите Dispose для объекта перед всеми ссылками ...) :

var ms = new MemoryStream(Encoding.Default.GetBytes(DefaultControlTemplateXaml));
using(ms)
{
    var x = XamlReader.Load(ms);
    _defaultControlTemplate = x as ControlTemplate;
}

Однако этот другой кусок не является:

var ms = new MemoryStream(Encoding.Default.GetBytes(DefaultControlTemplateXaml));
try
{
    var x = XamlReader.Load(ms);
    _defaultControlTemplate = x as ControlTemplate;
}
finally { ms.Dispose(); }

Согласно документации Microsoft :

Оператор using гарантирует, что Dispose вызывается, даже если возникает исключение во время вызова методов для объекта. Вы можете достичь того же результата, поместив объект в блок try и затем вызвав Dispose в блоке finally ; на самом деле это то, как оператор using переводится компилятором .

Так что я действительно в растерянности ... разве эти два утверждения не должны быть идентичными?

Обновление

Так как люди настаивают (не читая мой комментарий) на объяснении этики using. Я скажу так:

  using (var ms = new MemoryStream(Encoding.Default.GetBytes(DefaultControlTemplateXaml)))
  {
    var x = XamlReader.Load(ms);
    _defaultControlTemplate = x as ControlTemplate;
  }

Это все еще дает CA2000 на fxcop, поэтому оригинальный вопрос остается.

Обновление 2

Добавление нескольких снимков экрана, чтобы вы могли видеть, что это Visual Studio 2010 и вся функция.

Первая версия (выдает предупреждение): With warning

Вторая версия (ок): Correct build

Ответы [ 3 ]

4 голосов
/ 16 марта 2012

(Удалены некоторые материалы, не относящиеся к вопросу, а также некоторые некорректные сведения о ThreadAbortException.)

Возможно, вы столкнулись с ложным срабатыванием, о котором сообщил CA2000.Вы можете искать Microsoft Connect для CA2000 .Существует довольно много проблем (не все они являются ошибочно-положительными ошибками).

Я лично отключил CA2000 в некоторых проектах из-за этих ложноположительных результатов.Я использую Visual Studio 2010 с анализом кода, и я только что проверил, что да, после того, как мне пришлось слишком часто подавлять CA2000, мы решили отключить его в проекте, над которым я сейчас работаю.

0 голосов
/ 16 марта 2012

Существует разница в двух частях кода, которая может быть причиной того, почему FxCOP помечает один, а не другой.

Обратите внимание, что анализ кода в Visual Studio 2010 Premium не помечает ни один фрагмент кода с этим предупреждением, поэтому может быть добавлено некоторое понимание по сравнению с более старыми версиями FxCOP.

В любом случае, разница в том, что в действительности блок использования не переводится в блок try / catch, показанный в вопросе.

Вот лучший перевод:

var ms = new MemoryStream(Encoding.Default.GetBytes(DefaultControlTemplateXaml));
var temp = (IDisposable)ms;
try
{
    var x = XamlReader.Load(ms);
    _defaultControlTemplate = x as ControlTemplate;
}
finally
{
    if (temp != null)
        temp.Dispose();
}

Обратите внимание, что я не говорю, что это является причиной вашего предупреждения, я просто говорю, что это одно различие между двумя частями кода.

0 голосов
/ 16 марта 2012

Правильный код будет

using(var ms= new MemoryStream(Encoding.Default.GetBytes(DefaultControlTemplateXaml)))
{
    var x = XamlReader.Load(ms);
    _defaultControlTemplate = x as ControlTemplate;
}

Вы должны объявить и назначить внутри оператора using. Затем он вызовет распоряжение должным образом

Редактировать: уточнить справочную задачу

Полагаю, вы делаете следующее:

var ms;
using(ms= new MemoryStream(Encoding.Default.GetBytes(DefaultControlTemplateXaml)))
{
    var x = XamlReader.Load(ms);
    _defaultControlTemplate = x as ControlTemplate;
}

тогда вы можете использовать переменную ms после ее удаления. Это то, о чем говорится в Послании. Или, может быть, вы назначаете ms другой переменной внутри блока using.

...