Click to Rate and Give Feedback
MSDN
MSDN Library
.NET Development
Previous Versions
.NET Framework 3.0
Tools
Development Tools
FxCop
FxCop Warnings
Usage Warnings
 Implement ISerializable correctly
Collapse All/Expand All Collapse All
This page is specific to
Microsoft Visual Studio 2005/.NET Framework 2.0

Other versions are also available for the following:
Visual Studio Team System
Implement ISerializable correctly

TypeName

ImplementISerializableCorrectly

CheckId

CA2240

Category

Microsoft.Usage

Breaking Change

NonBreaking

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

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.

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.

Do not exclude a warning from this rule.

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.
Tags What's this?: Add a tag
Community Content   What is Community Content?
Add new content RSS  Annotations
A better way to implement ISerializable      David M. Kean - MSFT ... SHelm   |   Edit   |   Show History

While the example above shows one way to implement ISerializable, it is often better in C# to implement ISerializable.GetObjectData explicity and have that call a protected method or in Visual Basic implement ISerializable.GetObjectData directly using a protected method. This saves you from polluting your class's public API with methods that consumers will never need to call directly.

The following example shows a class that does this.

[C#]
 
using System;
using System.Security.Permissions;
using System.Runtime.Serialization;
 
namespace Samples
{
[Serializable]
public class Book : ISerializable
{
private string _Text;
 
        public Book(string text)
{
if (text == null)
throw new ArgumentNullException("text");
 
            _Text = text;
}
     
        protected Book(SerializationInfo info, StreamingContext context)
{
if (info == null)
throw new ArgumentNullException("info");
 
            _Text = info.GetString("Text");            
}
       
        public string Text
{
get { return _Text; }
}
        
        protected virtual void GetObjectData(SerializationInfo info, StreamingContext context)
{
info.AddValue("Text", _Text);
}
        
        [SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.SerializationFormatter)]
void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context)
{
if (info == null)
throw new ArgumentNullException("info");
 
            GetObjectData(info, context);
}
}
}
 

[Visual Basic]
 
Imports System
Imports System.Security.Permissions
Imports System.Runtime.Serialization
 
Namespace Samples
 
    <Serializable()> _
Public Class Book
Implements ISerializable
 
        Private _Text As String
 
        Public Sub New(ByVal text As String)
            If (text Is Nothing) Then Throw New ArgumentNullException("text")
  
_Text = text
        End Sub
 
        Protected Sub New(ByVal info As SerializationInfo, ByVal context As StreamingContext)
            If (info Is Nothing) Then Throw New ArgumentNullException("info")
 
            _Text = info.GetString("Text")
        End Sub
 
        Public ReadOnly Property Text() As String
Get
Return _Text
End Get
End Property
  
<SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags:=SecurityPermissionFlag.SerializationFormatter)> _
Protected Overridable Sub GetObjectData(ByVal info As SerializationInfo, ByVal context As StreamingContext) _
            Implements ISerializable.GetObjectData
            If (info Is Nothing) Then Throw New ArgumentNullException("info")
 
            info.AddValue("Text", _Text)
        End Sub
 
    End Class
 
End Namespace
Tags What's this?: Add a tag
Flag as ContentBug
An easy way to test serialization code      David M. Kean - MSFT ... SHelm   |   Edit   |   Show History

The hardest part about developing serializable classes, is testing that ISerializable has actually been implemented correctly. To help you do this, make use of the following helper method that tests the serialization of an object by serializing to and then deserializing from a binary stream directly in memory. This will cause both the serialization constructor and ISerializable.GetObjectData implementation to be called.

  [C#]
   
  using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
   
  public static class SerializationTester
{
public static T RoundTrip<T>(T value)
{
if (value == null)
throw new ArgumentNullException("value");
   
          using (MemoryStream stream = new MemoryStream())
{
BinaryFormatter formatter = new BinaryFormatter();
formatter.Serialize(stream, value);
   
              stream.Seek(0, SeekOrigin.Begin);
   
              return (T)formatter.Deserialize(stream);
}
}
}

  [Visual Basic]
   
  Imports System.IO
Imports System.Runtime.Serialization.Formatters.Binary
   
  Public Module SerializationTester
   
      Public Function RoundTrip(Of T)(ByVal value As T) As T
If value Is Nothing Then Throw New ArgumentNullException("value")
   
          Using stream As New MemoryStream()
  
Dim formatter As New BinaryFormatter()
              formatter.Serialize(stream, value)
   
              stream.Seek(0, SeekOrigin.Begin)
   
              Return DirectCast(formatter.Deserialize(stream), T)
  
End Using
  
End Function
  
End Module

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

  [C#]
  
  Book book = new Book("This is the book's text.");
  book = SerializationTester.RoundTrip(book);
   
  Console.WriteLine(book.Text);

  [Visual Basic]
   
  Dim book As New Book("This is the book's text.")
  book = SerializationTester.RoundTrip(book)
   
  Console.WriteLine(book.Text)

The above example outputs the following:

  This is the book's text.
Tags What's this?: Add a tag
Flag as ContentBug
Processing
© 2009 Microsoft Corporation. All rights reserved. Terms of Use | Trademarks | Privacy Statement
Page view tracker