可序列化和继承,正确使用,CA2236
本文关键字:CA2236 继承 序列化 | 更新日期: 2023-09-27 18:10:09
我有一个关于在继承类中正确实现isserializable的问题。
我有两个类,AbstractBaseClass
和它的实现BaseClass
。在BaseClass
衍生的FinalClass
实施后,我得到CA警告:
CA2236在isserializable类型上调用基类方法"FinalClass。FinalClass(SerializationInfo, StreamingContext)'应该是修改为调用其基类实现。
我不明白的是,如果提取的info.GetString("FileName")
和info.GetString("Password")
足以创建FinalClass
的实例,为什么我应该调用基类?
问题:
有人能给我解释一下吗?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);
}
}
因为,一般来说,这将是一个合理的建议。如果您更改了基实现中的某些内容,调用base将确保一切都将继续工作。
编译器没有和你一样的知识。你知道没有必要调用base,编译器不会。编译器知道所做的并不违法,所以它只是发出一个警告,告诉你有一些可能需要你注意的代码(警告总是应该引起你的注意)。
如果确实是您想要的,请忽略警告,但我个人会调用基构造函数,就像编译器建议的那样。
你现在所做的并没有错perse这是完全有效的c#代码,但编译器决定发出警告,因为它"知道"(为了简单起见)ISerializable
与序列化构造函数的组合通常是如何实现的。
假设在下一个迭代中BaseClass
添加了自己的一些属性,Foo属性,并假设我们希望将该属性(反)序列化。您可能会在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)
构造函数。这就是这个警告的全部内容。该设置不是未来的证明,将来任何对AbstractBaseClass
或BaseClass
的添加都应该在构造函数中反序列化,而在当前实现而不是中将被反序列化。
所以,是的,你可以说当前的实现是一个设计错误,尽管我可能更倾向于称之为设计的错误实现。