CA2000 передает объектную ссылку на базовый конструктор в C # - PullRequest
10 голосов
/ 22 апреля 2010

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

Я программирую ячейку с нарисованной на заказ ячейкой, используемую в элементе управления DataGridView.Код напоминает:

public class DataGridViewMyCustomColumn : DataGridViewColumn
{
    public DataGridViewMyCustomColumn() : base(new DataGridViewMyCustomCell())
    {
    }

. Он генерирует следующее предупреждение:

CA2000: Microsoft.Reliability: в методе 'DataGridViewMyCustomColumn.DataGridViewMyCustomColumn ()' вызывается System.IDisposable.Dispose onобъект 'new DataGridViewMyCustomCell ()' до того, как все ссылки на него выйдут из области видимости.

Я понимаю, что это предупреждает меня. DataGridViewMyCustomCell (или класс, от которого он наследуется) реализует интерфейс IDisposable и Dispose () метод должен быть вызван для очистки любых ресурсов, заявленных DataGridViewMyCustomCell, когда его больше нет.

В примерах, которые я видел в интернете, предлагается использование блока для определения времени жизни объекта и автоматического его удаления системой, но база не распознается при перемещении в тело конструктора, поэтому яя не могу написать блок using вокруг него ... что я не уверен, что хотел бы делать в любом случае, так как это не указывало бы во время выполнения освободить объект, который еще можно было бы использовать позже внутри базового класса?

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

Ответы [ 2 ]

18 голосов
/ 22 апреля 2010

Если вы используете Visual Studio 2010, то CA2000 полностью сломан.Он также может быть поврежден в других версиях FxCop (он же Code Analysis), но VS2010 - единственная, за которую я могу поручиться.Наша кодовая база выдает предупреждения CA2000 для кода, подобного этому ...

internal static class ConnectionManager 
{
    public static SqlConnection CreateConnection()
    {
         return new SqlConnection("our connection string");
    }
}

..., указывающего, что соединение не удаляется до того, как оно выйдет за рамки метода.Ну, да, это правда, но это не выходит за рамки для приложения , так как оно возвращается вызывающей стороне - в этом весь смысл метода!Таким же образом, ваш аргумент конструктора не выходит за пределы области видимости, а передается в базовый класс, поэтому это скорее ложное срабатывание из правила, чем реальная проблема.

Раньше это было полезноправило, но теперь все, что вы можете сделать, это выключить его, пока они не исправят это.К сожалению, потому что (очень мало) фактических положительных моментов - это то, что должно быть исправлено.

1 голос
/ 19 февраля 2014

Не существует безопасного и элегантного способа передачи цепочечному конструктору нового объекта IDisposable в базовый конструктор, поскольку, как вы заметили, невозможно заключить вызов цепочечного конструктора в любой тип блока try finally. Есть подход, который безопасен, но вряд ли элегантен: определите метод утилиты примерно так:

internal static TV storeAndReturn<TR,TV>(ref TR dest, TV value) where TV:TR
{ 
  dest = value; return value;
}

Пусть конструктор будет выглядеть примерно так:

protected DataGridViewMyCustomColumn(ref IDisposable cleaner) : 
   base(storeAndReturn(ref cleaner, new DataGridViewMyCustomCell()))
{
}

Код, которому нужен новый объект, должен затем вызывать открытый статический метод фабрики, который будет вызывать соответствующий конструктор в блоке try / finally, основная строка которого обнулится cleaner непосредственно перед его завершением, и чей блок finally будет вызывать Dispose на cleaner, если он не равен нулю. При условии, что каждый подкласс определяет аналогичный метод фабрики, этот подход гарантирует, что новый объект IDisposable будет удален, даже если исключение происходит между моментом его создания и моментом, когда инкапсулирующий объект предоставляется клиентскому коду. Узор уродлив, но я не уверен, что какой-либо более приятный образец обеспечит корректность.

...