FxCop (/VS2010 Code Analysis), можно ли теперь пометить результат метода как ответственность вызывающей стороны для IDisposable?

Если я напишу следующий код:

public void Execute()
{
    var stream = new MemoryStream();
    ...
}

тогда анализ кода пометит это как:

Предупреждение 1 CA2000: Microsoft.Reliability: в методе «ServiceUser.Execute()» вызовите System.IDisposable.Dispose для объекта «поток», прежде чем все ссылки на него будут вне области действия. C:\Dev\VS.NET\DisposeTest\DisposeTest\ServiceUser.cs 14 DisposeTest

Однако, если я создам фабричный шаблон, мне все равно может потребоваться избавиться от объекта, но теперь FxCop/Code Analysis не жалуется. Скорее, он жалуется на фабричный метод, а не на код, который его вызывает. (Кажется, у меня был пример, который жаловался на фабричный метод, но тот, который я публикую здесь, не , поэтому я вычеркнул это)

Есть ли способ, например, с помощью атрибутов, перенести ответственность за объект IDisposable из фабричного метода на вызывающую сторону?

Возьмите этот код:

public class ServiceUser
{
    public void Execute()
    {
        var stream = StreamFactory.GetStream();
        Debug.WriteLine(stream.Length);
    }
}

public static class StreamFactory
{
    public static Stream GetStream()
    {
        return new MemoryStream();
    }
}

В этом случае никаких предупреждений нет. Я бы хотел, чтобы FxCOP/CA по-прежнему жаловался на мой первоначальный метод. Я по-прежнему обязан обращаться с этим объектом.

Могу ли я как-нибудь сообщить об этом FxCOP/CA? Например, недавно я рискнул изучить атрибуты аннотаций, которые предоставляет ReSharper, чтобы сообщить информацию об аналитическом механизме, которую иначе он не смог бы понять.

Итак, я представляю что-то вроде этого:

public static class StreamFactory
{
    [return: CallerResponsibility]
    public static Stream GetStream()
    {
        return new MemoryStream();
    }
}

Или этот дизайн далеко?


person Lasse V. Karlsen    schedule 12.12.2011    source источник


Ответы (1)


Существует разница между FxCop 10 (поставляется с Windows 7 и .NET 4.0 SDK) и Code Analysis 2010 (поставляется с Visual Studio Premium и выше). Code Analysis 2010 имеет набор дополнительных правил, который включает сильно улучшенную версию правил IDisposable.

При использовании Code Analysis 2010 в Visual Studio Premium фабрика не помечается (поскольку правило теперь видит, что переменная IDisposable возвращается вызывающему методу). Однако метод получения также не помечен из-за одного из крайних случаев исключения из правила. Существует список имен методов, которые вызывают срабатывание правила. Если вы переименуете свой метод GetStream в CreateStream, внезапно сработает правило:

Warning 4   CA2000 : Microsoft.Reliability : In method 'ServiceUser.Execute()',
call System.IDisposable.Dispose on object 'stream' before all references to it are out
of scope.   BadProject\Class1.cs    14  BadProject

Мне не удалось найти список префиксов методов, которые будут работать. Я пробовал некоторые из них, и Create~, Open~ запускали правило, многие другие, которые, как вы могли бы ожидать, не сработают, включая Build~, Make~, Get~.

Кроме того, существует длинный список ошибок, связанных с этим правилом. Правило было изменено в Visual Studio 2010, чтобы вызывать меньше ложных срабатываний, но теперь оно иногда пропускает элементы, которые должно было быть помечено (и было бы помечено в предыдущей версии). Не хватило времени, чтобы исправить правила во временных рамках Visual Studio 2010 (проверьте комментарии к отчету об ошибке).

С грядущими компиляторами Roslyn анализ кода, вероятно, получит серьезное обновление, до тех пор можно ожидать только незначительных обновлений. Текущая сборка Visual Studio Dev11 не запускается там, где вы хотите.

Итак, в заключение, отсутствие вашего атрибута не сильно поможет, поскольку правило уже определяет, что вы передаете IDisposable в качестве возвращаемого значения. Таким образом, анализ кода знает, что удалять его перед возвратом нехорошо. Если вы используете недокументированные правила именования, правило сработает. Возможно, атрибут может расширить правила именования, но я бы предпочел, чтобы Microsoft действительно исправила фактическое правило.

Я создал ошибка подключения, требующая документирования руководства по именованию в документация по правилам.

Комментарий от Microsoft:

Опубликовано Microsoft 19 января 2012 г. в 10:41 Здравствуйте!

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

Как вы указали в потоке stackoverflow, исторически было много проблем с надежностью этого правила, и отключение имен было добавлено внутренней деталью реализации, чтобы попытаться уменьшить количество ложных срабатываний. Однако это не считается предписывающим руководством о том, как разработчики должны называть свои методы, оно было добавлено после обзора общих практик кодирования. Мы считаем, что долгосрочное исправление заключается в повышении надежности правила, а не в добавлении руководства по именованию в нашу общедоступную документацию на основе внутренних деталей реализации, которые будут продолжать меняться по мере улучшения правила.

С уважением, команда анализа кода Visual Studio

person jessehouwing    schedule 14.12.2011