Implement ISerializable correctly

TypeName

ImplementISerializableCorrectly

CheckId

CA2240

Category

Microsoft.Usage

Breaking Change

NonBreaking

Cause

An externally visible type is assignable to the System.Runtime.Serialization.ISerializable interface and one of the following conditions is true:

Rule Description

Instance fields that are declared in a type that inherits the System.Runtime.Serialization.ISerializable interface are not automatically included in the serialization process. To include the fields, the type must implement the GetObjectData method and the serialization constructor. If the fields should not be serialized, apply the NonSerializedAttribute attribute to the fields to explicitly indicate the decision.

In types that are not sealed, implementations of the GetObjectData method should be externally visible, so that the method can be called by derived types, and overridable.

How to Fix Violations

To fix a violation of this rule, make the GetObjectData method visible and overridable and make sure all instance fields are included in the serialization process or explicitly marked with the NonSerializedAttribute attribute.

When to Exclude Warnings

Do not exclude a warning from this rule.

Example

The following example shows a derived serializable type with a serializable field that violates the rule and a type that satisfies the rule by correctly implementing the GetObjectData method.

The example above shows how to implement ISerializable method. In C#, it is often better to implement ISerializable.GetObjectData method explicitly and have it call a protected method. In Visual Basic, implement ISerializable.GetObjectData directly using a protected method. This saves you implementing methods in the public API that consumers will never need to call directly.

The following example shows a class that does this.

To test if ISerializable has been implemented correctly create a helper method, a method that tests the serialization of an object by serializing to and then desterilizing from a binary stream directly in memory. This will call both the serialization constructor and ISerializable.GetObjectData implementation.

The example above allows you to do the following (this block uses the Book class from above).

The above example outputs the following:

Output

This is the book's text.

Call base class methods on ISerializable types

Implement serialization constructors

Implement serialization methods correctly

Mark all non-serializable fields

Mark ISerializable types with serializable

Provide deserialization methods for optional fields

Secure GetObjectData overrides

Secure serialization constructors