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)
因为,一般来说,这将是合理的建议.如果你在基础实现中改变某些东西,调用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)构造函数.这就是这个警告的全部情况.设置不是未来证明,并且在构造函数中也应该反序列化的任何一个AbstractBaseClass或BaseClass将来的任何添加都将在当前实现中不被反序列化.
所以是的,你可以说当前的实现是一个设计错误,虽然我可能更可能称它为错误的设计实现.