Должен ли объект .Net / C # вызывать Dispose () для себя? - PullRequest
34 голосов
/ 18 февраля 2011

Ниже приведен пример кода, написанного коллегой.Это, очевидно, неправильно для меня, но я хотел проверить.Должен ли объект вызывать свой собственный метод Dispose () из одного из своих собственных методов?Мне кажется, что только владелец / создатель объекта должен вызывать Dispose () , когда это делается с объектом, а не с самим объектом.

Это веб-метод .asmx, который вызывает Утилизируйте () на себя, когда закончите.(Тот факт, что это веб-метод, вероятно, является второстепенным для вопроса в целом.) В нашей кодовой базе мы иногда создаем экземпляры классов веб-служб в методах других веб-служб, а затем вызываем методы для них.Если мой код делает это для вызова этого метода, объект возвращается, когда метод возвращается, и я больше не могу использовать этот объект.

[WebMethod]
public string MyWebMethod()
{
    try
    {
        return doSomething();
    }
    catch(Exception exception)
    {
        return string.Empty;
    }
    finally
    {
        Dispose(true);
    }
}

ОБНОВЛЕНИЕ: найдено несколько ссылок, связанных:

Нужно ли располагать ссылкой на веб-службу в ASP.NET?

Удалите класс прокси веб-службы?

Ответы [ 8 ]

34 голосов
/ 18 февраля 2011

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

4 голосов
/ 18 февраля 2011

если я когда-нибудь увижу это в одном из моих проектов, я бы спросил, почему, и я на 99,9999% уверен, что я все равно его удалю

для меня это своего рода запах красного флага / кода

3 голосов
/ 24 июля 2014

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

У меня есть несколько приложений, которые "запускают и забывают" темы. Использование этой методологии позволяет объекту самостоятельно распоряжаться.

Это помогает поддерживать чистоту среды без процесса диспетчера потоков.

1 голос
/ 18 февраля 2011

Нет технических ограничений на то, что разрешено делать методу Dispose.Единственное, что в этом особенного - это то, что Dispose вызывается в определенных конструкциях (foreach, using).Из-за этого Dispose может быть разумно использован, чтобы пометить объект как более неиспользуемый, особенно если вызов идемпотентен.

Однако я бы не использовал его для этой цели из-за принятой семантики Dispose,Если бы я хотел пометить объект как недоступный для использования внутри самого класса, я бы создал метод MarkUnuseable (), который мог бы вызываться с помощью Dispose или любого другого места.

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

0 голосов
/ 18 февраля 2011

Нет!Это неожиданное поведение и нарушает руководящие принципы передовой практики.Никогда не делай ничего беспрецедентного.Ваш объект должен делать только то, что необходимо для поддержания его состояния, при этом защищая целостность объекта для вызывающей стороны.Вызывающий абонент решит, когда это будет сделано (или GC, если ничего не будет).

0 голосов
/ 18 февраля 2011

Хотя объект .Net обычно не вызывает Dispose для себя, бывают случаи, когда код, выполняющийся внутри объекта, может быть последним, кто ожидает его использования.В качестве простого примера, если метод Dispose может обрабатывать очистку частично созданного объекта, может быть полезно иметь конструктор, закодированный примерно так:

Sub New()
  Dim OK As Boolean = False
  Try
    ... do Stuff
    OK = True
  Finally
    If Not OK Then Me.Dispose
  End Try
End Sub

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

Что касается вашего конкретного фрагмента кода, шаблон несколько необычен, но выглядит как способ передачи сокета.из одного потока в другой.Есть вызов, который возвращает массив байтов и делает недействительным Socket;этот массив байтов может использоваться в другом потоке для создания нового экземпляра Socket, который принимает поток связи, установленный другим Socket.Обратите внимание, что данные, относящиеся к открытому сокету, по сути являются неуправляемым ресурсом, но их нельзя очень хорошо обернуть в объект с финализатором, потому что они часто собираются передать тому, что сборщик мусора не может увидеть.*

0 голосов
/ 18 февраля 2011

Технически да, если этот «метод» является финализатором, и вы реализуете шаблон Finalize и IDisposable , как указано в Microsoft.

0 голосов
/ 18 февраля 2011

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

...