当我使用XmlSerialiser对其进行反序列化时,为什么我的DbNull不是单例?

我一直认为DbNull.value是一个单身人士。 因此你可以做这样的事情:

VB.NET:

If someObject Is DbNull.Value Then ... End if 

C#:

 If (someObject == DbNull.Value) { ... } 

但是最近,我使用XmlSerialiser序列化了一个DbNull实例,突然间它不再是单例了。 类型比较操作(如C#(obj是DBNull))工作正常。

代码如下:

 [Serializable, System.Xml.Serialization.XmlInclude(typeof(DBNull))] public class SerialiseMe { public SerialiseMe() { } public SerialiseMe(object value) { this.ICanBeDbNull = value; } public Object ICanBeDbNull { get; set; } } public void Foo() { var serialiseDbNull = new SerialiseMe(DBNull.Value); var serialiser = new System.Xml.Serialization.XmlSerializer(typeof(SerialiseMe)); var ms = new System.IO.MemoryStream(); serialiser.Serialize(ms, serialiseDbNull); ms.Seek(0, System.IO.SeekOrigin.Begin); var deSerialisedDbNull = (SerialiseMe)serialiser.Deserialize(ms); // Is false, WTF! var equalsDbNullDeserialised = deSerialisedDbNull.ICanBeDbNull == DBNull.Value; // Is false, WTF! var refEqualsDbNullDeserialised = object.ReferenceEquals(deSerialisedDbNull.ICanBeDbNull, DBNull.Value); // Is true. var convertIsDbNullDeserialised = Convert.IsDBNull(deSerialisedDbNull.ICanBeDbNull); // Is true. var isIsDbNullDeserialised = deSerialisedDbNull.ICanBeDbNull is DBNull; } 

为什么会这样? 它是如何发生的? 它可能发生在任何其他静态字段中吗?

PS:我知道VB代码示例正在进行参考比较,而c#正在调用Object.Equals。 两者都与DBNull具有相同的行为。 我通常使用VB。

虽然DBNull.Value是一个static readonly并且只作为单个实例存在…当您反序列化时,序列化代码将从流中的“数据”创建类DBNull的新实例。 由于DBNull.Value只是一个DBNull实例,因此序列化无法知道它是一个“特殊”实例。

注意:
出于同样的原因,如果您使用序列化然后反序列化的“单例”实例创建自己的类,您将获得完全相同的行为。 虽然反序列化的实例与原始实例无法区分,但它们不是同一个实例

你的c#代码不等于调用.Equals方法。 没有经过测试我真的很确定你是否替换

 someObject == DbNull.Value 

 DbNull.Value.Equals(someObject) 

它会给你预期的结果。 对于一些关于等式运算符和Equals方法的内容,请看一下: Eric Lipperts关于该主题的博客文章