【问题标题】:Why isn't my DbNull a singleton when I deserialise it using XmlSerialiser?当我使用 XmlSerializer 反序列化它时,为什么我的 DbNull 不是单例?
【发布时间】:2009-06-04 05:03:58
【问题描述】:

我一直认为 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。

【问题讨论】:

  • 我已经搞砸了几个小时非常相似的事情......我什至没有想过尝试 IS DBNull。

标签: c# .net xml-serialization singleton dbnull


【解决方案1】:

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

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

【讨论】:

  • 呸!魔术序列化代码上的一个痘痘。塔的答案虽然。
【解决方案2】:

您的 c# 代码不等于调用 .Equals 方法。如果没有测试,我实际上很确定你是否替换了

someObject == DbNull.Value

DbNull.Value.Equals(someObject) 

它会给你预期的结果。有关等式运算符和 Equals 方法的一些内部信息,请查看: Eric Lipperts blog post on that subject

【讨论】:

  • 我之前没有尝试过 Equals() 的组合,但它不起作用。 Object.RefEquals(obj, DbNull.Value), Object.Equals(obj, DbNull.Value), obj == DBNull.Value, DbNull.Value.Equals(obj) 反序列化后都返回false。
猜你喜欢
  • 1970-01-01
  • 2014-08-28
  • 2013-03-05
  • 2021-04-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-01-18
  • 1970-01-01
相关资源
最近更新 更多