2015-08-26 2 views
5

В нескольких местах люди предложили использовать private void Dispose(bool) для шаблона IDisposable. Это кажется устаревшим хотя (по крайней мере для незапечатанных классов), поскольку новый предложенный шаблон (согласно Microsoft) - protected virtual void Dispose(bool).private void Dispose (bool)?

Дело в том, что Code Analysis не сообщает private void Dispose(bool) за нарушение CA1063, даже если оно, похоже, нарушает шаблон напрямую.

Что случилось с этим? ? Является ли private void Dispose(bool) как-то вызывлся (или скомпилирован к чему-то, что выглядит как protected virtual Dispose(bool)

Если это какой-то вопрос с анализом кода и неправильная картина, есть способы, чтобы обнаружить это Возможно с StyleCop

Edit?: После рассмотрения, это, что базовый класс может назвать base.Dispose(), который ударит private void Dispose(bool) Даже если он не в состоянии передать в качестве аргумента

Edit:? Sample

public class A : IDisposable 
{ 
    ~A() 
    { 
     this.Dispose(false); 
    } 

    public void Dispose() 
    { 
     this.Dispose(true); 
     GC.SuppressFinalize(this); 
    } 

    private void Dispose(bool disposing) // Should be protected virtual void Dispose(bool) 
    { 
     Console.WriteLine("A"); 
    } 
} 

public class B : A 
{ 
    protected virtual void Dispose(bool disposing) // Proper pattern. 
    { 
     Console.WriteLine("B"); 
    } 
} 

public static class Program 
{ 
    static void Main(string[] args) 
    { 
     A a = new A(); 
     a.Dispose(); // Prints "A" 

     B b = new B(); 
     b.Dispose(); // Prints "A"! 
    } 
} 

Как вы можете видеть из этого, это делает использование шаблона размещения полностью громоздким.

Вы можете обойти это немного, спрятав public void Dispose(void) и затем позвонив base.Dispose(). Затем это работает «аналогично» правильному шаблону утилизации при вызове B b = new B(); b.dispose();, за исключением при вызове A b = new B(); b.Dispose();, который вызывает только A метод Dispose.

public class B : A 
{ 
    public void Dispose() // Causes CA error with or without "new". 
    { 
     this.Dispose(true); 
     GC.SuppressFinalize(this); 
    } 

    protected virtual void Dispose(bool disposing) // Proper pattern. 
    { 
     base.Dispose(); // Writes "A" (without quotes). 
     Console.WriteLine("B"); 
    } 
} 

В целом, все это кажется ужасным. Знаем ли мы, является ли это ошибкой, что CA принимает private void Dispose(bool) и есть ли способ хотя бы бросить предупреждение с помощью StyleCop?

Редактировать: Я не думаю, что я должен согласиться с ответом Александра, поскольку относительно вопроса, который у меня есть, в основном сводится к «Может быть ошибка», а также что-то, что должно быть комментарием. Если у кого-то еще есть что-то более убедительное, я думаю, что это будет более подходящий ответ.

+0

Что относительно закрытых классов? Защищенный должен использоваться для открытых классов, для закрытых. –

+0

Это работает для любого вопроса. Мы обнаружили несколько мест, где непечатаемые классы не бросали проблему. Это имеет смысл, однако, что частный требуется для закрытых классов. Тем не менее, было бы неплохо, если бы CA выбросил, если класс был вскрыт (и он также должен это знать). Я думаю, что мое редактирование показывает, почему он не может быть полностью из леса, чтобы он не бросал, но это все еще немного раздражает. –

+0

Вызов 'base.Dispose()' будет явным нарушением шаблона, поэтому я не думаю, что он его объясняет. Я согласен с вашей оригинальной мыслью, что Code Analysis должен сообщить о вашем случае. – sstan

ответ

6

Implementing a Dispose Method

интерфейс IDisposable требует реализацию одного метода без параметров, Dispose. Однако, модель отчуждать требуетдва Dispose методов быть реализованы:

  • публичной невиртуальной (ненаследуемым в Visual Basic) IDisposable.Dispose реализации, которая не имеет никаких параметров.
  • Защищенный виртуальный (Overridable in Visual Basic) метод Dispose.

Поскольку общественного, невиртуальные (ненаследуемая в Visual Basic), без параметров метода Dispose вызываются потребителем типа, его цель состоит в том, чтобы освободить неуправляемые ресурсы и указать, что финализации, если один присутствует, не нужно запускать. Из-за этого, он имеет стандартную реализацию:

public void Dispose() 
{ 
    // Dispose of unmanaged resources. 
    Dispose (true); 
    // Suppress finalization. 
    GC.SuppressFinalize (this); 
} 

Во второй перегрузке, утилизация параметр представляет собой Логическое значение, указывающее, поступает ли вызов метода из Dispose метода (его значение истины) или из финализатор (его значение ложно).

Когда сборщик мусора решает, что ваш объект больше не нужен, он не будет пытаться завершить его в случае, если вы забыли вызвать метод без параметров Dispose, потому что если вы сделали, и вы по образцу, вызов будет подавлено.

См: How Finalization Works

Private против Protected Virtual:

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

Почему некоторые люди используют приватную версию? Возможно, потому что наследование никогда не было их намерением, особенно если вы просто генерируете методы «на лету» с помощью таких инструментов, как Resharper, большую часть времени эти методы будут закрытыми.

Почему анализ кода не сообщает о проблеме?

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

+0

Добавить некоторые образцы. –

+0

Что нужно сделать для Dispose (bool), когда bool является true и false? – AksharRoop

+0

В конце страницы (https://msdn.microsoft.com/en-us/library/system.object.finalize.aspx) вы увидите пример. Если true, вы должны распоряжаться всеми ресурсами, потому что вы называемый методом dispose и хотите, чтобы вся использованная память была обратно. Если false, это означает, что сборщик мусора удаляет объект, тогда вам нужно только удалить неуправляемые ресурсы (объекты, созданные за пределами вашего приложения C#), остальные объекты могут быть оставлены нетронутыми по мере удаления сборщика мусора когда это необходимо. –

Смежные вопросы