CA2240: ISerializable を正しく実装します

TypeName

ImplementISerializableCorrectly

CheckId

CA2240

カテゴリ

Microsoft.Usage

互換性に影響する変更点

なし

原因

外部から参照できる型が System.Runtime.Serialization.ISerializable インターフェイスに適用でき、次のいずれかの条件に当てはまります。

  • 型は ISerializable.GetObjectData メソッドを継承しますがオーバーライドしていません。また、System.NonSerializedAttribute 属性でマークされていないインスタンス フィールドを型で宣言しています。

  • 型はシールされていません。また、外部から参照できませんがオーバーライドできる GetObjectData メソッドを型で実装しています。

規則の説明

System.Runtime.Serialization.ISerializable フィールドを継承する型で宣言されているインスタンス フィールドは、シリアル化プロセスに自動的には含まれません。 フィールドを含めるには、型で GetObjectData メソッドとシリアル化コンストラクターを実装します。 フィールドをシリアル化しない場合、フィールドに NonSerializedAttribute 属性を適用し、シリアル化しないことを明示します。

シールされない型の場合、GetObjectData メソッドの実装は外部から参照できるようにします。 そのため、メソッドは、派生型から呼び出すことができ、オーバーライドされます。

違反の修正方法

この規則違反を修正するには、GetObjectData メソッドを外部から参照できるようにし、オーバーライドできるようにします。また、すべてのインスタンス フィールドをシリアル化プロセスに含めるか、NonSerializedAttribute 属性で明示的にマークします。

警告を抑制する状況

この規則による警告は抑制しないでください。

使用例

この規則に違反する、2 つのシリアル化できる型を次の例に示します。


Imports System
Imports System.Security.Permissions
Imports System.Runtime.Serialization

Namespace Samples1

    ' Violates this rule
    <Serializable()> _
    Public Class Book
        Implements ISerializable

        Private ReadOnly _Title As String

        Public Sub New(ByVal title As String)
            If (title Is Nothing) Then Throw New ArgumentNullException("title")
            _Title = title
        End Sub

        Protected Sub New(ByVal info As SerializationInfo, ByVal context As StreamingContext)
            If (info Is Nothing) Then Throw New ArgumentNullException("info")

            _Title = info.GetString("Title")
        End Sub

        Public ReadOnly Property Title() As String
            Get
                Return _Title
            End Get
        End Property

        <SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags:=SecurityPermissionFlag.SerializationFormatter)> _
        Public Sub GetObjectData(ByVal info As SerializationInfo, ByVal context As StreamingContext) _
            Implements ISerializable.GetObjectData

            If (info Is Nothing) Then Throw New ArgumentNullException("info")

            info.AddValue("Title", _Title)
        End Sub
    End Class

    ' Violates this rule
    <Serializable()> _
    Public Class LibraryBook
        Inherits Book

        Private ReadOnly _CheckedOut As Date

        Public Sub New(ByVal text As String, ByVal checkedOut As Date)
            MyBase.New(text)
            _CheckedOut = checkedOut
        End Sub

        Public ReadOnly Property CheckedOut() As Date
            Get
                Return _CheckedOut
            End Get
        End Property

    End Class
End Namespace
using System;
using System.Security.Permissions;
using System.Runtime.Serialization;

namespace Samples1
{
    // Violates this rule
    [Serializable]
    public class Book : ISerializable
    {
        private readonly 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; }
        }

        [SecurityPermission(SecurityAction.Demand, SerializationFormatter = true)]
        public void GetObjectData(SerializationInfo info, StreamingContext context)
        {
            if (info == null)
                throw new ArgumentNullException("info");

            info.AddValue("Text", _Text);
        }
    }

    // Violates this rule
    [Serializable]
    public class LibraryBook : Book
    {
        private readonly DateTime _CheckedOut;

        public LibraryBook(string text, DateTime checkedOut)
            : base(text)
        {
            _CheckedOut = checkedOut;
        }

        public DateTime CheckedOut
        {
            get { return _CheckedOut; }
        }
    }
}
using namespace System;
using namespace System::Security::Permissions;
using namespace System::Runtime::Serialization;

namespace Samples1 
{
    // Violates this rule
    [Serializable]
    public ref class Book : ISerializable
    {
    private:
        initonly String^ _Title;

    public: 
        Book(String^ title)
        {
            if (title == nullptr)
                throw gcnew ArgumentNullException("title");

            _Title = title;
        }

        property String^ Title
        {
            String^ get()
            {
                return _Title;
            }
        }

    protected: 
        Book(SerializationInfo^ info, StreamingContext context)
        {
            if (info == nullptr)
                throw gcnew ArgumentNullException("info");

            _Title = info->GetString("Title");
        }

    private:
        [SecurityPermission(SecurityAction::LinkDemand, Flags = SecurityPermissionFlag::SerializationFormatter)]
        void virtual GetObjectData(SerializationInfo^ info, StreamingContext context) sealed = ISerializable::GetObjectData
        {
            if (info == nullptr)
                throw gcnew ArgumentNullException("info");

            info->AddValue("Title", _Title);
        }
    };

    // Violates this rule
    [Serializable]
    public ref class LibraryBook : Book
    {
        initonly DateTime _CheckedOut;

    public:
        LibraryBook(String^ title, DateTime checkedOut) : Book(title)
        {
            _CheckedOut = checkedOut;
        }

        property DateTime CheckedOut
        {
            DateTime get()
            {
                return _CheckedOut;
            }
        }
    };
}

Book クラスでオーバーライド可能な [ISerializable.GetObjectData] を実装し、Library クラスで [ISerializable.GetObjectData] を実装することによって上記の 2 つの違反を修正する例を次に示します。

Imports System
Imports System.Security.Permissions
Imports System.Runtime.Serialization

Namespace Samples2

    <Serializable()> _
    Public Class Book
        Implements ISerializable

        Private ReadOnly _Title As String

        Public Sub New(ByVal title As String)
            If (title Is Nothing) Then Throw New ArgumentNullException("title")
            _Title = title
        End Sub

        Protected Sub New(ByVal info As SerializationInfo, ByVal context As StreamingContext)
            If (info Is Nothing) Then Throw New ArgumentNullException("info")

            _Title = info.GetString("Title")
        End Sub

        Public ReadOnly Property Title() As String
            Get
                Return _Title
            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("Title", _Title)
        End Sub
    End Class


    <Serializable()> _
    Public Class LibraryBook
        Inherits Book

        Private ReadOnly _CheckedOut As Date

        Public Sub New(ByVal text As String, ByVal checkedOut As Date)
            MyBase.New(text)
            _CheckedOut = checkedOut
        End Sub

        Protected Sub New(ByVal info As SerializationInfo, ByVal context As StreamingContext)
            MyBase.New(info, context)

            _CheckedOut = info.GetDateTime("CheckedOut")
        End Sub

        Public ReadOnly Property CheckedOut() As Date
            Get
                Return _CheckedOut
            End Get
        End Property

        <SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags:=SecurityPermissionFlag.SerializationFormatter)> _
        Protected Overrides Sub GetObjectData(ByVal info As System.Runtime.Serialization.SerializationInfo, _
                                              ByVal context As System.Runtime.Serialization.StreamingContext)

            MyBase.GetObjectData(info, context)

            info.AddValue("CheckedOut", _CheckedOut)
        End Sub
    End Class
End Namespace
using System;
using System.Security.Permissions;
using System.Runtime.Serialization;

namespace Samples2
{
    [Serializable]
    public class Book : ISerializable
    {
        private readonly string _Title;

        public Book(string title)
        {
            if (title == null)
                throw new ArgumentNullException("title");

            _Title = title;
        }

        protected Book(SerializationInfo info, StreamingContext context)
        {
            if (info == null)
                throw new ArgumentNullException("info");

            _Title = info.GetString("Title");
        }

        public string Title
        {
            get { return _Title; }
        }

        [SecurityPermission(SecurityAction.Demand, SerializationFormatter = true)]
        protected virtual void GetObjectData(SerializationInfo info, StreamingContext context)
        {
            info.AddValue("Title", _Title);
        }

        [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.SerializationFormatter)]
        void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context)
        {
            if (info == null)
                throw new ArgumentNullException("info");

            GetObjectData(info, context);
        }
    }

    [Serializable]
    public class LibraryBook : Book
    {
        private readonly DateTime _CheckedOut;

        public LibraryBook(string title, DateTime checkedOut)
            : base(title)
        {
            _CheckedOut = checkedOut;
        }

        protected LibraryBook(SerializationInfo info, StreamingContext context)
            : base(info, context)
        {
            _CheckedOut = info.GetDateTime("CheckedOut");
        }

        public DateTime CheckedOut
        {
            get { return _CheckedOut; }
        }

        [SecurityPermission(SecurityAction.Demand, SerializationFormatter = true)]
        protected override void GetObjectData(SerializationInfo info, StreamingContext context)
        {
            base.GetObjectData(info, context);

            info.AddValue("CheckedOut", _CheckedOut);
        }
    }
}
using namespace System;
using namespace System::Security::Permissions;
using namespace System::Runtime::Serialization;

namespace Samples2 
{
    [Serializable]
    public ref class Book : ISerializable
    {
    private:
        initonly String^ _Title;

    public: 
        Book(String^ title)
        {
            if (title == nullptr)
                throw gcnew ArgumentNullException("title");

            _Title = title;
        }

        property String^ Title
        {
            String^ get()
            {
                return _Title;
            }
        }

    protected: 
        Book(SerializationInfo^ info, StreamingContext context)
        {
            if (info == nullptr)
                throw gcnew ArgumentNullException("info");

            _Title = info->GetString("Title");
        }

        [SecurityPermission(SecurityAction::LinkDemand, Flags = SecurityPermissionFlag::SerializationFormatter)]
        void virtual GetObjectData(SerializationInfo^ info, StreamingContext context) = ISerializable::GetObjectData
        {
            if (info == nullptr)
                throw gcnew ArgumentNullException("info");

            info->AddValue("Title", _Title);
        }
    };

    [Serializable]
    public ref class LibraryBook : Book
    {
        initonly DateTime _CheckedOut;

    public:
        LibraryBook(String^ title, DateTime checkedOut) 
            : Book(title)
        {
            _CheckedOut = checkedOut;
        }

        property DateTime CheckedOut
        {
            DateTime get()
            {
                return _CheckedOut;
            }
        }

    protected: 
        LibraryBook(SerializationInfo^ info, StreamingContext context) : Book(info, context)
        {
            _CheckedOut = info->GetDateTime("CheckedOut");
        }

        [SecurityPermission(SecurityAction::LinkDemand, Flags = SecurityPermissionFlag::SerializationFormatter)]
        void virtual GetObjectData(SerializationInfo^ info, StreamingContext context) override
        {
            Book::GetObjectData(info, context);
            info->AddValue("CheckedOut", _CheckedOut);
        }
    };
}

関連規則

CA2236: ISerializable 型で基本クラス メソッドを呼び出します

CA2229: シリアル化コンストラクターを実装します

CA2238: シリアル化メソッドを正しく実装します

CA2235: すべてのシリアル化不可能なフィールドを設定します

CA2237: ISerializable 型を SerializableAttribute に設定します

CA2239: オプションのフィールドに逆シリアル化メソッドを指定します

CA2120: シリアル化コンストラクターをセキュリティで保護します