Утилизация требуется при использовании интерфейса - PullRequest
1 голос
/ 16 сентября 2010

Допустим, у меня есть MyObject объект, который имеет два интерфейса: IMyContract и IDisposable.И у меня есть этот код в методе:

IMyContract blah = new MyObject();
blah.Blah();
return;

Это потенциальная утечка памяти, верно?Разве это не должно быть:

using (MyObject blah = new MyObject())
{
    blah.Blah();
}
return;

Ответы [ 4 ]

6 голосов
/ 16 сентября 2010

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

(Просто чтобы уточнить: память - это минимум вероятность утечки, поскольку IDisposable обычно относится к неуправляемым ресурсам, таким как сетевые подключения и т. Д. Это возможно, конечно, - объект может иметь дескриптор некоторой памяти, выделенной далеко от взгляда GC.1008 *, который содержит прямые ссылки на неуправляемые ресурсы, также должен иметь финализатор, поэтому утечка должна быть только временной ... но это все равно может быть болезненным.)

1 голос
/ 16 сентября 2010

Если IDisposable - это , реализованное правильно (с финализатором, который вызывает Dispose() и не SuppressFinalize), сборщик мусора в конечном итоге доберется до него.Тем не менее, using() - это то же самое, что и try { ... } finally { object.Dispose(); }, которое будет детерминировано (явно, как можно скорее).Если вы зависите от сборщика мусора, вы можете быть удивлены, сколько времени потребуется для его утилизации.Если есть неуправляемые ресурсы, вы можете быстро их исчерпать, потому что они не были освобождены.

Редактировать: Я пропустил суть этого в первый раз.Да, когда вы используете MyObject, вы должны Dispose() правильно с using().Если у вас есть другой код, который использует этот интерфейс, то вы можете получить что-то вроде:

public IMyContract GetInterface()
{
  using (MyObject obj = new MyObject())
  {
    obj.DoSomething();
    return (IMyContract)obj;
  }
}

Остальная часть кода может затем использовать IMyContract contract = GetInterface();, не беспокоясь о (или даже не зная), что вещи должны быть расположены.

1 голос
/ 16 сентября 2010

вы также можете вызвать dispose в вашем первом примере:

IMyContract blah = new MyObject();
blah.Blah();
((IDisposable)blah).Dispose();
return;

не совсем так чисто, но иногда вы должны использовать интерфейсы.

Другая возможность для вашего интерфейса - наследовать IDisposable. Тогда вы можете использовать:

using (IMyContract blah = new MyObject())
{
    blah.Blah();
}
return;
0 голосов
/ 16 сентября 2010

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

Если разработчики из IMyContract обычно являются одноразовыми (или, вероятно, могут быть одноразовыми), то IMyContract должно наследоваться от IDisposable.В противном случае вы могли бы просто MyObject наследовать от IDisposable.

В любом случае, объект обязательно должен быть удален.

...