Все ли исключения.NET сериализуемы?
Можно ли сериализовать все объекты исключений.NET?
5 ответов
И да и нет. Как указали Джефф и другие, все классы исключений должны и почти всегда являются сериализуемыми. Если вы столкнетесь с определенным классом исключений, который не сериализуем, это вполне возможно ошибка.
Но при рассмотрении сериализуемости необходимо учитывать как непосредственный класс, так и все типы, которые являются членами этого типа (это рекурсивный процесс). Базовый класс Exception имеет свойство Data, которое имеет тип IDictionary. Это проблематично, поскольку позволяет вам или кому-либо еще добавлять любой объект в Исключение. Если этот объект не сериализуем, сериализация исключения не будет выполнена.
Реализация свойства Data по умолчанию выполняет некоторую базовую проверку, чтобы убедиться, что добавляемый объект сериализуем. Но это имеет недостатки в нескольких отношениях
- Только проверка верхнего уровня для сериализуемости типа, и эта проверка выполняется только путем проверки Type.IsSerializable (не 100% -ной проверки).
- Недвижимость виртуальная. Производный тип исключения может переопределить и использовать Hashtable, который выполняет проверку 0.
Да, но исторически были (без каламбура) исключения.
Другими словами, все исключения ДОЛЖНЫ быть сериализуемыми, но некоторые пользовательские исключения из стороннего кода могут отсутствовать в зависимости от того, как они реализованы.
Например, в эпоху.NET 1.0 исключения из официального поставщика баз данных Microsoft Oracle не были сериализуемыми из-за ошибок в их коде.
На этот вопрос уже достаточно ответили, но для программистов, которые плохо знакомы с C# или с сериализацией, я думаю, что на самом деле очень полезно указать, что в общем случае исключения НЕ сериализуемы!
Это может звучать немного провокационно, но позвольте мне объяснить.
Это правда, что все исключения реализуют интерфейс ISerializable, но это только говорит о том, что он должен быть сериализуемым. Но реализация интерфейса НЕ делает объект Serializable (что в этом контексте подразумевает, что Исключение может быть как сериализовано, так и десериализовано).
Наиболее точный ответ на этот вопрос, как отмечали другие, заключается в том, что многие, но, безусловно, не все исключения в .Net Framework являются сериализуемыми. Но если в вопросе используется термин "Исключение.Net" в более широкой области, например, Исключение, полученное из System.Exception, то лучшим и более полезным ответом с точки зрения наилучшей практики и избежания ошибок является утверждение, которое я сделал выше., что в целом исключения не являются сериализуемыми.
И вот почему: как указывалось ранее, чтобы исключение было действительно сериализуемым, оно должно иметь правильный конструктор ctor(SerializationInfo, StreamingContext)
и он должен быть украшен соответствующим атрибутом. Важно отметить, что ни одно из этих ограничений не вызывает ошибок компилятора, если они опущены!
Это означает, что никакой класс, полученный из Exception, не может быть сериализуемым, если не предприняты эти дополнительные, необязательные (с точки зрения компилятора) шаги.
Т.е. любой неопытный / неосведомленный кодер, который получает новое исключение, как показано ниже, только что создал исключение, которое НЕ сериализуемо.
class MyNewException : Exception { }
Visual Studio имеет отличный фрагмент "Exception", который позволяет довольно быстро генерировать новые сериализуемые исключения. Но даже в этом случае нечего напоминать или помогать программисту фактически сериализировать свойства объекта. Например, даже если класс ниже имеет соответствующий конструктор и атрибут, MyNewField
свойство не будет сериализовано без дополнительного кода как в конструкторе, так и в GetObjectData.
class MyNewException : Exception
{
public MyNewField { get; set; }
}
Итак, основной момент здесь заключается в том, что если вы по какой-то причине должны полагаться на правильную сериализацию и десериализацию исключений, следует полностью осознавать, что когда речь идет о каком-либо пользовательском коде или сборках, нет никаких гарантий, что он будет работать. Кроме того, поскольку требуемый конструктор обычно защищен, вы не обязательно сможете легко проверить его наличие (без отражения).
В моих собственных проектах я в некоторых моментах создал исключение "Прокси", которое может хранить некоторую информацию (например, Сообщение и т. Д.) Из Исключений, которые сами по себе не сериализуемы. Они могут использоваться для сериализации некоторой информации или в качестве альтернативы для десериализации данных, записанных в исключении, которое не имеет соответствующего конструктора.
System.Exception
инвентарь ISerializable
, но потомки могут не десериализоваться, если они не реализуют правильный перегруженный конструктор с подписью (SerializationInfo,StreamingContext)
,
System.Exception
инвентарь ISerializable
и это базовый класс для всех исключений, так что да.
Смотрите: http://msdn.microsoft.com/en-us/library/system.exception.aspx