Анализатор обнаружил подозрительный класс, декорированный атрибутом [Serializable] и имеющий члены несериализуемых типов (т.е. типов, которые сами не декорированы этим атрибутом). При этом, несериализуемые члены не помечены атрибутом [NonSerialized]. Наличие таких членов может, при использовании некоторых стандартных классов для сериализации, привести к возникновению исключения типа 'SerializationException' при попытке сериализации экземпляра данного класса.
Рассмотрим пример. Предположим, что у нас есть метод, выполняющий сериализацию и десериализацию объекта:
static void Foo(MemoryStream ms, BinaryFormatter bf, C1 obj) { bf.Serialize(ms, obj); ms.Position = 0; obj = (C1)bf.Deserialize(ms); }
Имеются следующие определения классов 'C1' и 'NonSerializedClass':
sealed class NonSerializedClass { } [Serializable] class C1 { private Int32 field1; private NotSerializedClass field2; }
При попытке сериализации экземпляра класса 'C1' возникнет исключение типа 'SerializationException', так как декорирование класса атрибутом [Serializable] подразумевает, что все поля будут сериализованы. Но тип поля 'field2' не сериализуем, что приведёт к возникновению исключения. Для решения проблемы поле 'field2' необходимо декорировать атрибутом [NonSerialized]. Тогда корректное определение класса 'C1' может выглядеть так:
[Serializable] class C1 { private Int32 field1; [NonSerialized] private NotSerializedClass field2; }
Со свойствами ситуация несколько отличается. Рассмотрим пример ошибочного класса:
[Serializable] class C2 { private Int32 field1; public NonSerializedClass Prop { get; set; } }
К свойствам нельзя применить атрибут [NonSerialized]. Тем не менее, при попытке сериализовать такой класс, например, с использованием 'BinaryFormatter', будет сгенерировано исключение. Дело в том, что автоматически реализуемые свойства компилятором раскрываются в поле и методы получения значения этого свойства и, возможно, записи. В этом случае будет выполняться сериализация не самого свойства, а поля, сгенерированного компилятором. Эта ситуация аналогична описанному ранее примеру с полем.
Ошибку можно исправить, явно реализовав свойство через какое-то поле. Тогда корректный код будет выглядеть так:
[Serializable] class C2 { private Int32 field1; [NonSerialized] private NonSerializedClass nsField; public NonSerializedClass Prop { get { return nsField; } set { nsField = value; } } }
Взгляните на примеры ошибок, обнаруженных с помощью диагностики V3097. |