Могу ли я безопасно очистить поле только для чтения? - PullRequest
6 голосов
/ 22 октября 2010

Допустим, у меня есть класс с полем объекта. Когда вызывается Dispose (), я хотел бы очистить ссылку на этот объект. Закрытое поле может быть установлено только один раз, поэтому в идеале я хотел бы, чтобы оно было доступно только для чтения, но если оно доступно только для чтения, возникает ошибка времени компиляции, когда я пытаюсь освободить ссылку на объект во время Dispose (). В идеале я хотел бы иметь безопасную утилизацию И пометить поле _value как только для чтения. Это возможно или даже необходимо?

public class Foo : IDisposable
{
      public Foo(object value)
      {
            _value = value;
      }

      public object Value { get { return _value; } }
      private readonly object _value;

      public void Dispose()
      {
            //Cleanup here
            _value = null     // causes compile time error
      }
}

Ответы [ 4 ]

4 голосов
/ 22 октября 2010

Установка ссылки на ноль на самом деле ничего не делает. Сборщик мусора очистит объект, когда на него больше не будет ссылок, что в данном случае, поскольку вы делаете это в методе Dispose, предположительно, экземпляр Foo больше не будет иметь никаких ссылок на него, и разница в выбор времени, вероятно, не имеет смысла. Как правило, вы реализуете шаблон Dispose, потому что ваш тип имеет в качестве члена класс, который сам реализует IDisposable (в данном случае тип - Object, который не реализует IDisposable), или у вас есть неуправляемые ресурсы, которые вы хотите выпускать детерминистически. Вы можете найти описание шаблона Dispose здесь . Обратите внимание, что если вы создаете переменную-член только для чтения типа, который реализует IDisposable, вы можете вызвать метод Dispose для этого объекта внутри вашего метода Dispose:

public class SomeClass : IDisposable
{
    private Boolean mDisposed;
    private readonly MemoryStream mStream = new MemoryStream(); // Could be any class that implements IDisposable
    public void Dispose() {
        Dispose(true);
        GC.SuppressFinalize(this);
    }
    protected void Dispose(Boolean disposing) {
        if (disposing & !mDisposed) {
            mStream.Dispose();  // Could and should call Dispose
            mDisposed = true;
        }
        return;
    }
}

Это работает, потому что только для чтения природа ссылается на объект, а не на сам объект.

3 голосов
/ 22 октября 2010

Это не обязательно, даже если бы это было возможно.

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

1 голос
/ 22 октября 2010

Это не нужно и не правильно. Желание сделать то, что вы спрашиваете в своем вопросе, похоже, указывает на то, что вы где-то обращаетесь к удаленному объекту, и это неправильно.

Вместо того, чтобы пытаться выполнить то, что вы просили, вам, возможно, следует реализовать IsDisposed (кстати, это часть стандартного шаблона Dispose ) и сначала проверить его.

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

0 голосов
/ 31 мая 2013

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

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

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

...