Я реализую IDisposable правильно?

Прямо сейчас (в Swift 2.3), если вы используете:

myString.characters.count 

метод вернет тип «Distance», если вам нужен метод для возврата Integer, вы должны напечатать приведение следующим образом:

var count = myString.characters.count as Int
28
задан mafu 8 May 2013 в 08:53
поделиться

7 ответов

Вам не нужно использовать эту расширенную версию реализации IDisposable, если ваш класс не использует напрямую неуправляемые ресурсы.

Простого

 public virtual void Dispose()
 {

     _Writer.Dispose();
 }

будет достаточно.

Если вашему потребителю не удается удалить ваш объект, он будет GC, как правило, без вызова Dispose, объект, удерживаемый _Writer, также будет GC, и у него будет финализатор, поэтому он все равно сможет очистить его неуправляемый ресурсы правильно.

Править

Проведя некоторое исследование ссылок, предоставленных Мэттом и другими, я пришел к выводу, что мой ответ здесь стоит . Вот почему: -

Предпосылка одноразовой реализации "шаблона" (под этим я подразумеваю защищенный виртуальный Dispose (bool), SuppressFinalize и т. Д. Marlarky) наследуемого класса состоит в том, что подкласс может держатся за неуправляемый ресурс.

Однако в реальном мире подавляющее большинство из нас, разработчиков .NET, даже близко не подходят к неуправляемым ресурсам. Если бы вам нужно было количественно оценить " было бы разумно. Следовательно, в значительно большем объеме «нормального» кода нам не нужно беспокоиться о всей этой ерунде. Если нам нужен IDisposable, мы можем использовать простой шаблон выше, наследуемый или нет.

Уф, рад снять это с моей груди. ;)

39
ответ дан 28 November 2019 в 02:54
поделиться

Вам не нужен метод Finalize (деструктор), поскольку у вас нет неуправляемых объектов. Однако вы должны оставить вызов GC.SuppressFinalize на тот случай, если класс, наследующий от Foo, имеет неуправляемые объекты и, следовательно, финализатор.

Если вы сделаете класс запечатанным, то вы знаете, что неуправляемые объекты являются никогда не будет входить в уравнение, поэтому нет необходимости добавлять перегрузку защищенного виртуального удаления (bool) или GC.SuppressFinalize .

Изменить:

@ AnthonyWJones возражает против этого: если вы знаете, что подклассы не будут ссылаться на неуправляемые объекты, все Dispose (bool) и GC.SuppressFinalize не нужны. Но в этом случае вам действительно нужно сделать классы внутренними , а не общедоступными , а метод Dispose () должен быть виртуальным . Если вы знаете, что делаете, то не стесняйтесь следовать предложенному Microsoft шаблону, но вы должны знать и понимать правила, прежде чем нарушать их!

16
ответ дан 28 November 2019 в 02:54
поделиться

Вы должны проверить, что _Writer не null , прежде чем пытаться его удалить. (Это не Кажется вероятным, что он когда-нибудь будет null , но на всякий случай!)

protected virtual void Dispose(bool disposing)
{
    if (!_Disposed)
    {
        if (disposing && (_Writer != null))
        {
            _Writer.Dispose();
        }
        _Writer = null;
        _Disposed = true;
    }
}
1
ответ дан 28 November 2019 в 02:54
поделиться

Рекомендуется использовать финализатор только тогда, когда у вас есть неуправляемые ресурсы (например, собственные дескрипторы файлов, указатели памяти и т. Д.).

У меня есть два небольших предложения,

Это не обязательно иметь Переменная " m_Disposed " для проверки вы ранее вызывали Dispose на ваших управляемых ресурсах. Ты мог бы используйте аналогичный код, например,

 protected virtual void Dispose (bool dispose)
{
 if (удаление) {
 если (_Writer! = ноль)
 _Writer.Dispose ();
 }
 _Writer = null;
}

Открывайте файлы столько, сколько необходимо. Итак, в вашем примере вы должны проверить наличие файла в конструкторе, используя File.Exists , а затем, когда вам нужно прочитать / записать файл, , затем вы откроете его и используйте его.

Кроме того, если вы просто хотите записать текст в файл, посмотрите File.WriteAllText или File.OpenText или даже File. AppendText , предназначенный для текстовых файлов с ASCIIEncoding .

В остальном, да, вы правильно реализуете шаблон .NET Dispose .

4
ответ дан 28 November 2019 в 02:54
поделиться

Если вы откроете StreamWriter, вам также придется его удалить, иначе возникнет утечка.

0
ответ дан 28 November 2019 в 02:54
поделиться

У меня много таких классов - и я рекомендую сделать класс запечатан по возможности. IDisposable + наследование может работать, но в 99% случаев оно вам не нужно - и с ним легко ошибиться.

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

просто выполните:

public sealed class Foo : IDisposable
{
    private StreamWriter _Writer;

    public Foo(string path)
    {
            FileStream fileWrite = File.Open (path, FileMode.OpenOrCreate, FileAccess.Write, FileShare.ReadWrite);
            try { 
                _Writer = new StreamWriter (fileWrite, new ASCIIEncoding());
            } catch {
                fileWrite.Dispose();
                throw;
            }
    }

    public void Dispose()
    {
         _Writer.Dispose();
    }
}

Обратите внимание на try ... catch; технически конструктор StreamWriter может вызвать исключение, Википедия: Финализаторы C ++ / CLI и автоматические переменные .

Например, реализация «безопасного» одноразового контейнера в C ++ / CLI выглядит так ...

public ref class MyDisposableContainer
{
    auto_handle<IDisposable> kidObj;
    auto_handle<IDisposable> kidObj2;
public:

    MyDisposableContainer(IDisposable^ a,IDisposable^ b) 
            : kidObj(a), kidObj2(b)
    {
        Console::WriteLine("look ma, no destructor!");
    }
};

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

Не то, чтобы я был большим поклонником C ++ / CLI, но для кода, сильно ориентированного на ресурсы, он легко превзошел C #, и он имеет абсолютно блестящее взаимодействие как с управляемым, так и с собственным кодом - короче говоря, идеальный связующий код ;-) . Я стараюсь писать 90% своего кода на C #, но использую C ++ / CLI для всех нужд взаимодействия (особенно.

3
ответ дан 28 November 2019 в 02:54
поделиться

" Комментарии к документации XML (Руководство по программированию на C #) обычно не предполагается, что он играет с управляемыми объектами, когда их удаляет финализатор (который вам в любом случае не нужен, как указывали другие).

0
ответ дан 28 November 2019 в 02:54
поделиться
Другие вопросы по тегам:

Похожие вопросы: