Все ли исключения .NET сериализуемы? - PullRequest
28 голосов
/ 05 декабря 2008

Можно ли сериализовать все объекты исключений .NET?

Ответы [ 5 ]

38 голосов
/ 05 декабря 2008

Да и нет. Как указали Джефф и другие, все классы исключений должны и почти всегда являются сериализуемыми. Если вы столкнетесь с определенным классом исключений, который не сериализуем, это вполне возможно ошибка.

Но при рассмотрении сериализуемости необходимо учитывать как непосредственный класс, так и все типы, которые являются членами этого типа (это рекурсивный процесс). Базовый класс Exception имеет свойство Data , которое имеет тип IDictionary. Это проблематично, поскольку позволяет вам или кому-либо еще добавлять любой объект в Исключение. Если этот объект не сериализуем, сериализация исключения не будет выполнена.

Реализация свойства Data по умолчанию выполняет некоторую базовую проверку, чтобы убедиться, что добавляемый объект сериализуем. Но это имеет недостатки в нескольких отношениях

  • Только проверка верхнего уровня для сериализуемости типа, и эта проверка выполняется только путем проверки Type.IsSerializable (не 100% -ной проверки).
  • Свойство является виртуальным. Производный тип исключения может переопределить и использовать Hashtable, который выполняет проверку 0.
15 голосов
/ 05 декабря 2008

Да, но исторически были (без каламбура) исключения.

Другими словами, все исключения ДОЛЖНЫ быть сериализуемыми , но некоторые пользовательские исключения из стороннего кода могут не быть, в зависимости от того, как они реализованы.

Например, в эпоху .NET 1.0 исключения из официального поставщика базы данных Microsoft Oracle не допускали сериализации из-за ошибок в их коде.

10 голосов
/ 06 декабря 2012

На этот вопрос уже достаточно ответа, но для программистов, которые плохо знакомы с C # или с сериализацией, я думаю, что на самом деле очень полезно указать, что в общем случае исключения НЕ сериализуемы!

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

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

Наиболее точный ответ на этот вопрос, как отмечали другие, заключается в том, что многие, но, безусловно, не все исключения в .Net Framework являются сериализуемыми. Но если вопрос использует термин «исключение .Net» в более широкой области, например, Исключение , полученное из System.Exception, тогда лучшим и более полезным ответом с точки зрения наилучшей практики и избежания ошибок является утверждение, которое я сделал выше, что в целом исключения не являются сериализуемыми.

И вот почему: Как указывалось ранее, для того, чтобы Исключение было действительно Сериализуемым, у него должен быть правильный конструктор ctor(SerializationInfo, StreamingContext), и он должен быть украшен соответствующим атрибутом. Важно отметить, что ни одно из этих ограничений не вызывает ошибок компилятора, если они опущены!

Это означает, что класс NO , полученный из Exception, является сериализуемым, если не предприняты эти дополнительные, необязательные (с точки зрения компилятора) шаги.

т.е. любой неопытный / незнакомый кодер, который получает новое исключение, как показано ниже, только что создал исключение, которое НЕ Сериализуемо.

class MyNewException : Exception { }

Visual studio имеет отличный фрагмент «Exception», который позволяет довольно быстро генерировать новые сериализуемые исключения. Но даже в этом случае нечего напоминать или помогать программисту фактически сериализировать свойства объекта. Например, даже если приведенный ниже класс имеет соответствующий конструктор и атрибут, свойство MyNewField не будет сериализовано без дополнительного кода как в конструкторе, так и в GetObjectData.

class MyNewException : Exception 
{
    public MyNewField { get; set; }
}

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

В моих собственных проектах в некоторых моментах я создал исключение "Прокси", которое может хранить некоторую информацию (например, сообщения и т. Д.) Из исключений, которые сами по себе не сериализуются. Их можно использовать для сериализации некоторой информации или в качестве альтернативы для десериализации данных, записанных в исключении, которое не имеет соответствующего конструктора.

6 голосов
/ 05 декабря 2008

System.Exception реализует ISerializable, но потомки могут не десериализоваться, если не реализуют правильный перегруженный конструктор с подписью (SerializationInfo,StreamingContext).

2 голосов
/ 05 декабря 2008

System.Exception реализует ISerializable, и это базовый класс для всех исключений, так что да.

См .: http://msdn.microsoft.com/en-us/library/system.exception.aspx

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...