ISerializable和继承,正确使用,CA2236

Vla*_*adL 1 .net c# inheritance serialization multiple-inheritance

我有一个关于继承类中ISerializable的正确实现的问题.

我有两个课程AbstractBaseClass及其实施BaseClass.的实施后FinalClass从派生BaseClass,我发现了CA警告:

CA2236 ISerializable类型的调用基类方法应修改方法'FinalClass.FinalClass(SerializationInfo,StreamingContext)'以调用其基类实现.

我不明白的是为什么我应该调用基类如果提取info.GetString("FileName")并且info.GetString("Password")足以创建实例FinalClass

问题:

1)有人可以向我解释一下吗?

2)如果我按原样保留并且只是压制警告,我是否有任何设计问题?

谢谢

简化的代码示例是:

public abstract class AbstractBaseClass : ISerializable
{
    [SecurityPermission(SecurityAction.Demand, SerializationFormatter = true)]
    public virtual void GetObjectData(SerializationInfo info, StreamingContext context)
    {
        info.AddValue ...
        //...
    }

    protected AbstractBaseClass() {  }
    protected AbstractBaseClass(SerializationInfo info, StreamingContext context)
    {
        if (info.GetInt32("Version") >= 1)
        {
            //...
        }
    }
}

public class BaseClass : AbstractBaseClass, ISerializable
{
    public BaseClass() : base() { }

    public override void GetObjectData(SerializationInfo info, StreamingContext context)
    {
        base.GetObjectData(info, context);
        info.AddValue ...
    }

    protected BaseClass(SerializationInfo info, StreamingContext context)
        : base(info, context)
    {
        if (info.GetInt32("Version") >= 1)
        {
            Connection = new MyConnection();
        }
    }
}

public class FinalClass : BaseClass
{
    public string FileName { get; private set; }
    public string Password { get; private set; }

    public FinalClass(string fileName, string password)
        : base()
    {
        FileName = fileName;
        Password = password;
    }

    protected FinalClass(SerializationInfo info, StreamingContext context)
        : this(info.GetString("FileName"), info.GetString("Password")) { }

    public override void GetObjectData(SerializationInfo info, StreamingContext context)
    {
        base.GetObjectData(info, context);
        info.AddValue("FileName", FileName);
        info.AddValue("Password", Password);
    }
}
Run Code Online (Sandbox Code Playgroud)

Wil*_*mpt 5

因为,一般来说,这将是合理的建议.如果你在基础实现中改变某些东西,调用base将确保一切都能继续工作.

编译器与您没有相同的知识.知道没有必要调用base,编译器没有.编译器确实知道你正在做的事情并不违法,所以它只是发出一个警告,告诉你有一些代码可能需要你的注意(警告总是引起你的注意).

如果这真的是你想要的,请取消警告,但我个人会调用基础构造函数,就像编译器建议的那样.

你现在正在做的是没有错的深灰色.它是完全有效的C#代码,但编译器决定发出警告,因为它"知道"(为简单起见)关于如何ISerializable与序列化构造函数组合通常实现.

假设在下一次迭代中BaseClass添加了它自己的一些属性,Foo属性,并假设我们想要该属性(de-)序列化.您可能会在BaseClass(SerializationInfo,StreamingContext)构造函数中实现反序列化所需的代码

public class BaseClass : AbstractBaseClass, ISerializable
{
    public int Foo { get; set; }

    protected BaseClass(SerializationInfo info, StreamingContext context)
        : base(info, context)
    {
        // ...
        Foo = info.GetInt32("Foo");
        // ...
  }
}
Run Code Online (Sandbox Code Playgroud)

在您当前的设置中,反序列化时FinalClass,BaseClass的Foo属性不会被反序列化,因为您决定调用this(string fileName, string password)构造函数而不是base(SerializationInfo, StreamingContext)构造函数.这就是这个警告的全部情况.设置不是未来证明,并且在构造函数中也应该反序列化的任何一个AbstractBaseClassBaseClass将来的任何添加都将在当前实现中被反序列化.

所以是的,你可以说当前的实现是一个设计错误,虽然我可能更可能称它为错误的设计实现.