﻿# V3097\. Possible exception: type marked by \[Serializable\] contains non\-serializable members not marked by \[NonSerialized\]\.

Анализатор обнаружил подозрительный класс, декорированный атрибутом \[Serializable\] и имеющий члены несериализуемых типов \(т\.е\. типов, которые сами не декорированы этим атрибутом\)\. При этом, несериализуемые члены не помечены атрибутом \[NonSerialized\]\. Наличие таких членов может, при использовании некоторых стандартных классов для сериализации, привести к возникновению исключения типа 'SerializationException' при попытке сериализации экземпляра данного класса\.

Рассмотрим пример\. Предположим, что у нас есть метод, выполняющий сериализацию и десериализацию объекта:

```cpp
static void Foo(MemoryStream ms, BinaryFormatter bf, C1 obj)
{
  bf.Serialize(ms, obj);
  ms.Position = 0;
  obj = (C1)bf.Deserialize(ms);
}
```

Имеются следующие определения классов 'C1' и 'NonSerializedClass':

```cpp
sealed class NonSerializedClass { }

[Serializable]
class C1
{
  private Int32 field1;
  private NotSerializedClass field2;
}
```

При попытке сериализации экземпляра класса 'C1' возникнет исключение типа 'SerializationException', так как декорирование класса атрибутом \[Serializable\] подразумевает, что все поля будут сериализованы\. Но тип поля 'field2' не сериализуем, что приведёт к возникновению исключения\. Для решения проблемы поле 'field2' необходимо декорировать атрибутом \[NonSerialized\]\. Тогда корректное определение класса 'C1' может выглядеть так:

```cpp
[Serializable]
class C1
{
  private Int32 field1;

  [NonSerialized]
  private NotSerializedClass field2;
}
```



Со свойствами ситуация несколько отличается\. Рассмотрим пример ошибочного класса:

```cpp
[Serializable]
class C2
{
  private Int32 field1;
  public NonSerializedClass Prop { get; set; }
}
```

К свойствам нельзя применить атрибут \[NonSerialized\]\. Тем не менее, при попытке сериализовать такой класс, например, с использованием 'BinaryFormatter', будет сгенерировано исключение\. Дело в том, что автоматически реализуемые свойства компилятором раскрываются в поле и методы получения значения этого свойства и, возможно, записи\. В этом случае будет выполняться сериализация не самого свойства, а поля, сгенерированного компилятором\. Эта ситуация аналогична описанному ранее примеру с полем\.

Ошибку можно исправить, явно реализовав свойство через какое\-то поле\. Тогда корректный код будет выглядеть так:

```cpp
[Serializable]
class C2
{
  private Int32 field1;

  [NonSerialized]
  private NonSerializedClass nsField;
  public NonSerializedClass Prop 
  { 
    get { return nsField; } 
    set { nsField = value; }
  }
}
```