Есть ли способ убедиться, что Dispose () вызывается при исключении во время десериализации класса IDisposable? - PullRequest
2 голосов
/ 29 июня 2009

в c #, я десериализирую объект типа, который реализует IDisposable со следующим оператором (только для иллюстрации).

XmlSerializer s = new XmlSerializer(typeof(MyDisposable))
MyDisposable o = (MyDispoable)s.Deserialize(filepath);

afaik, сериализатор пытается создать объект, используя ctor по умолчанию и назначая все открытые свойства и поля впоследствии. В случае возникновения каких-либо исключений я не получу руки на построенный объект.

Итак, мой вопрос: есть ли способ убедиться, что выделенные ресурсы автоматически освобождаются? мне известно о Dispose (bool dispose) - «шаблоне», реализующем явный финализатор, но я бы чувствовал себя более комфортно с явным освобождением любых ресурсов (т.е. детерминистически).

Ответы [ 6 ]

4 голосов
/ 29 июня 2009

Кажется, что необычный случай для DTO на самом деле иметь ресурсы для освобождения, поэтому я могу понять, если он не обеспечивает поддержку IDisposable в случае сбоя (мой собственный сериализатор тоже нет - поэтому я, конечно, не могу критиковать).

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

XmlSerializer не поддерживает обратные вызовы, в противном случае окончательный обратный вызов был бы возможной опцией для активной загрузки ресурсов (хотя и немного странно).

1 голос
/ 29 июня 2009
Предложение

A using - это то, что вы используете для детерминированного освобождения ресурсов:

using (MyDisposible o = (MyDisposible)s.Deserialize (filepath))
{
 // Do stuff with 0
}

Я бы спросил, почему ты хочешь это сделать. В C # вы хотите детерминистически освобождать вещи, только если они связаны с внешним физическим ресурсом, таким как соединение SQL или файл.

Сборщик мусора асимптотически более эффективен, чем ручное управление памятью, и рекомендуется, чтобы ссылки на память просто выходили из области видимости.

0 голосов
/ 22 июля 2009

Disposer и Finalizer - это не одно и то же в C #.

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

Вы можете использовать финализатор в C #, чтобы гарантировать, что даже если ваш утилизатор не вызван, вы все равно не потеряете ресурсы. Т.е. .Net гарантирует, что он попытается запустить ваш утилизатор до того, как он действительно соберет мусор.

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

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

0 голосов
/ 29 июня 2009

Как насчет вызова GC.Collect (0, GCCollectionMode.Forced) после получения исключения?

0 голосов
/ 29 июня 2009

Если в методе XmlSerializer.Deserialize возникает какое-либо исключение, оно распространяется на следующий метод catch, и ваш объект (o) не будет назначен. Поэтому, если вы не используете установщики свойств для выделения некоторых неуправляемых ресурсов во время десериализации , я не понимаю, почему вам следует заняться удалением объекта вручную.

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

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

0 голосов
/ 29 июня 2009

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

[Редактировать: Удалена точка о публичных полях, так как она неверна]
Я также оставляю этот ответ доступным для любой образовательной ценности, которую он может иметь -> прочитать комментарий Марка

...