powered by simpleCommunicator - 2.0.53     © 2025 Programmizd 02
Форумы / WinForms, .Net Framework [игнор отключен] [закрыт для гостей] / вопрос
16 сообщений из 16, страница 1 из 1
вопрос
    #39150944
Фотография Где-то в степи
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Правильно ли сконструировали тип?
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
 class Class:IDisposable
    {
        private readonly IDisposable _disposable;
        private bool _disposed;

        public Class(IDisposable disposable)
        {
            _disposable = disposable;
        }
       

        public void Dispose()
        {
            if (!_disposed)
            {
                 _disposable.Dispose();
                 GC.SuppressFinalize(this);
                _disposed = true;
            }
        }

         ~Class()
        {
            Dispose();
        }
    }
...
Рейтинг: 0 / 0
вопрос
    #39150949
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Код: c#
1.
private bool _disposed;


ЕМНИП надо инициализировать, дефолтных значений C# не признает, хотя и забивает все нулями.

По мне так излишество это, проще так
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
        public void Dispose()
        {
            if ( _disposable != null)
            {
                 _disposable.Dispose();
                 _disposable = null;
            }
        }
...
Рейтинг: 0 / 0
вопрос
    #39150959
Фотография Где-то в степи
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dima T,
да в общем то можно и добавить, класс не запечатан можно и virtual void Dispose(bool disposing) загрузить для тех кто пойдет после нас
да и свойство добавить для удобства IsDisposed как у контролов, вообще уместно ли реализовывать у типа Class - IDisposable?
...
Рейтинг: 0 / 0
вопрос
    #39151053
Сон Веры Павловны
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Где-то в степиПравильно ли сконструировали тип?
Не совсем, классическая реализация disposable-паттерна включает в себя два перегруженных метода Dispose - один public и без параметра, второй protected (либо private, если класс sealed) с параметром, указывающим на то, откуда происходит вызов - т.е. как-то так:
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
class Class:IDisposable
{
  private readonly IDisposable _disposable;
  private bool _disposed;

  public Class(IDisposable disposable)
  {
    _disposable = disposable;
  }
 

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

  protected virtual void Dispose(bool disposing)
  {
    if (_disposed) return;
    if (disposing)
      _disposable.Dispose();
  }

   ~Class()
  {
    Dispose(false);
  }
}


Выполнять вызов GC.SuppressFinalize при вызове Dispose из финализатора избыточно - объект уже попал в обработку из очереди на финализацию (а вот промаркировать его, как не требующего финализации, при вызове Dispose извне очень даже нужно и полезно). Плюс, если операция диспозинга сводится только к диспозингу инкапсулируемого объекта, то при вызове Dispose извне из очереди на финализацию нужно удалить и экземпляр объекта-враппера (Class).
Dima TЕМНИП надо инициализировать, дефолтных значений C# не признает, хотя и забивает все нулями.
Не надо:
10.4.4 Field initialization
The initial value of a field, whether it be a static field or an instance field, is the default value (Section 5.2) of the field's type.
Обязательны для инициализации локальные переменные, но не поля класса.
...
Рейтинг: 0 / 0
вопрос
    #39151055
Фотография Где-то в степи
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Сон Веры Павловны,
то есть если класс не sealed, виртуал желателен ( писал выше) а если не sealed - то и так сойдет?
...
Рейтинг: 0 / 0
вопрос
    #39151064
Сон Веры Павловны
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Где-то в степиСон Веры Павловны,
то есть если класс не sealed, виртуал желателен ( писал выше) а если не sealed - то и так сойдет?
Нет, перегрузка Dispose с параметром в общем случае нужна всегда. "И так сойдет" в том случае, если в вашем классе нужно осовбождать только managed-ресурсы, реализующие IDisposable. Если же нужно освобождать какие-то unmanaged-ресурсы (например, IntPtr на какой-нибудь буфер), то это освобождение должно выполняться всегда (см. здесь , например). И всё равно даже в таком случае рекомендуется сто раз подумать, нужен ли финализатор, т.к. сборка мусорных объектов с финализаторами намного затратнее, чем без финализаторов (у Рихтера это подробно расписано - почему и как). Рекомендуется, например, рассмотреть вариант с CriticalFinalizerObject.
Резюмируя: если у вас враппится только IDisposable-объект - оставил бы, как есть, и выкинул бы финализатор.
...
Рейтинг: 0 / 0
вопрос
    #39151069
Фотография Где-то в степи
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Сон Веры Павловны,
автороставил бы, как есть, и выкинул бы финализатор соглашусь,и пошел бы еще дальше - вообще
бы не реализовывал диспосабле в обертке.
а вот
авторто это освобождение должно выполняться всегда (см. здесь, например). И всё равно даже в таком случае рекомендуется сто раз подумать, нужен ли финализатор не соглашусь, где же защита от дурака - программист проспал using?
...
Рейтинг: 0 / 0
вопрос
    #39151072
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Где-то в степи не соглашусь, где же защита от дурака - программист проспал using?
Деструктор объекта вызывается сборщиком мусора, из-за этого и родились IDisposable, using и т.д.
...
Рейтинг: 0 / 0
вопрос
    #39151079
Сон Веры Павловны
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Где-то в степине соглашусь, где же защита от дурака - программист проспал using?
Выше же писал - например, CriticalFinalizerObject - это во-первых. Во-вторых - если у инкапсулируемого IDisposable есть финализатор, то у враппера он вообще не нужен. В третьих, обязательного-кровь-из-носу освобождения требуют только unmanaged-ресурсы, и то далеко не все - большинство из них автоматически освободятся при закрытии процесса (как хэндл глобального хоткея, например), так что "программист проспал using" не приведет к концу света.
Dima TГде-то в степи не соглашусь, где же защита от дурака - программист проспал using?
Деструктор объекта вызывается сборщиком мусора, из-за этого и родились IDisposable, using и т.д.
Вовсе нет, и даже почти с точностью до наоборот - вызов Dispose вполне детерминирован и явен, в отличие от вызова финализатора. Ну, и реализация disposable-паттерна имеет усеченные варианты, в которых финализатора нет.
...
Рейтинг: 0 / 0
вопрос
    #39151090
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Сон Веры ПавловныDima Tпропущено...

Деструктор объекта вызывается сборщиком мусора, из-за этого и родились IDisposable, using и т.д.
Вовсе нет, и даже почти с точностью до наоборот - вызов Dispose вполне детерминирован и явен, в отличие от вызова финализатора. Ну, и реализация disposable-паттерна имеет усеченные варианты, в которых финализатора нет.
Нагуглил что такое финализатор ИМХУ разработчики C# накосячили в синтаксисе: ~Class() это синтаксис описания деструктора в С++, что в итоге приводит к непонимаю как работает код.

Например в С++
Код: plaintext
1.
2.
3.
4.
{
  Class my_obj;
  ...
} // тут отработает my_obj.~Class()


а в C# так не произойдет. my_obj.~Class() будет вызван сборщиком мусора неизвестно когда, т.е. когда он решит сам прибраться или его об этом попросят.
Поэтому в отличии от того же C++ нельзя выносить освобождение ресурсов ОС в my_obj.~Class() т.к. это не деструктор. Например прога открыла файл (закрытие файла в финализаторе), написала туда чего-нибудь и уснула в ожидании какого-нибудь события. Файл продолжает быть открытым.

ИМХУ т.к. деструктора как-такого не предусмотрено, родились костыли в виде IDisposable.
...
Рейтинг: 0 / 0
вопрос
    #39151097
Сон Веры Павловны
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dima TИМХУ разработчики C# накосячили в синтаксисе: ~Class() это синтаксис описания деструктора в С++, что в итоге приводит к непонимаю как работает код.
Рихтер, CLR via C#If you’re familiar with C++, you’ll notice that the special syntax C# requires for defining a Finalize method looks just like the syntax you’d use to define a C++ destructor. In fact, the C# Programming Language Specification calls this method a destructor. However, a Finalize method doesn’t work like an unmanaged C++ destructor at all, and this has caused a great deal of confusion for developers migrating from one language to another. The problem is that developers mistakenly believe that using the C# destructor syntax means that the type’s objects will be deterministically destructed, just as they would be in C++. However, the CLR doesn’t support deterministic destruction, preventing C# from providing this mechanism.
Chapter 21 Automatic Memory Management (Garbage Collection) / Using Finalization to Release Native Resources
Видимо, вы этого не читали - почитайте, это полезная книга.

А IDisposable - вовсе не костыль, просто следует четко понимать разницу (касательно CLR) между освобождением ресурсов класса, и уничтожением самого экземпляра класса. Первая задача вполне управляема и детерминирована, вторая - неуправляема и недетерминирована (её выполняет GC). Даже если попытаться дернуть финализатор через рефлекшн (метод Finalize), это к освобождению памяти, заянтой под объект, не приведет.
...
Рейтинг: 0 / 0
вопрос
    #39151108
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Сон Веры ПавловныChapter 21 Automatic Memory Management (Garbage Collection) / Using Finalization to Release Native Resources
Видимо, вы этого не читали - почитайте, это полезная книга.
Читал. До этого не мог понять зачем вообще надо IDisposable.

С# пока изучаю, на С++ практики намного больше, а тут надо тупо помнить что пишется одинаково, а работает по-разному. Вот в чем мои претензии к синтаксису ~Class(). Не надо было теплое мягким называть, и проблем бы не было.

Тут 18703950 я именно об этом писал, т.е. предположил, что Где-то в степи решил что ~Class() отработает как деструктор в С++
...
Рейтинг: 0 / 0
вопрос
    #39152298
Arm79
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
...
Рейтинг: 0 / 0
вопрос
    #39152326
Фотография ЕвгенийВ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Где-то в степи,
Ха!
А что будет, если переданный disposable в своей реализации не вызовет GC.SuppressFinalize, но будет иметь переопределенный Finalize?
Кошмар! Это же страшное дело!
...
Рейтинг: 0 / 0
вопрос
    #39152463
Roman Mejtes
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
да ни чего не будет, если метод SuppressFinalize не будет вызвать в реализации Disposible, то объект просто будет поставлен в очередь на финализацию, а дальше уже зависит от реализации этого метода.
...
Рейтинг: 0 / 0
вопрос
    #39152469
Сон Веры Павловны
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Roman Mejtesда ни чего не будет, если метод SuppressFinalize не будет вызвать в реализации Disposible, то объект просто будет поставлен в очередь на финализацию, а дальше уже зависит от реализации этого метода.
Не будет удален из очереди на финализацию. Ставится от в эту очередь при создании экземпляра, когда CLR видит у объекта финализатор.
...
Рейтинг: 0 / 0
16 сообщений из 16, страница 1 из 1
Форумы / WinForms, .Net Framework [игнор отключен] [закрыт для гостей] / вопрос
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]