ISerializable和继承,正确使用,CA2236

时间:2014-06-25 11:30:25

标签: c# .net 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);
    }
}

1 个答案:

答案 0 :(得分:5)

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

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

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

你现在正在做的事情没有错误 perse 。它是完全有效的C#代码,但编译器决定发出警告,因为它知道&#34; (为简单起见),通常会实现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");
        // ...
  }
}

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

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