Pregunta

Siempre he asumido que DBNull.Value era un producto único. Y por lo tanto se podía hacer cosas como esta:

VB.NET:

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

C #:

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

Sin embargo, recientemente, me serializado una instancia DBNull utilizando el XmlSerialiser y de repente no era un producto único más. operaciones de comparación de tipos (como C # 's (obj es DBNull)) funcionan bien, aunque.

Código de la siguiente manera:

[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;

}

¿Por qué es este el caso? Y ¿cómo es posible? ¿Y puede suceder posiblemente con otros campos estáticos?

PD: Soy consciente del ejemplo de código VB está haciendo una comparación de referencia y C # es llamando Object.equals. Ambos tienen el mismo comportamiento con DBNull. Por lo general trabajo con VB.

¿Fue útil?

Solución

A pesar de que es un DBNull.Value static readonly y sólo existe como una sola instancia ... cuando serializar-DE, el código de serialización sería la creación de una nueva instancia de la clase desde el DBNull 'datos' en la corriente. Desde el DBNull.Value es simplemente una instancia DBNull, no hay manera de serialización a saber que es una instancia de 'especial'.

Nota:
Por la misma razón, si usted hace su propia clase con una instancia 'Singleton' que serializa y luego des-serializar obtendrá exactamente el mismo comportamiento. A pesar de que la instancia deserializado será indistinguible de la instancia original, no van a ser la misma instancia .

Otros consejos

Su código C # no es igual a una llamada al método .equals. Con fuera de haber probado que estoy realmente muy seguro de si sustituiste

someObject == DbNull.Value

con

DbNull.Value.Equals(someObject) 

le daría el resultado esperado. Para algunas tripas sobre el operador de igualdad y el método Equals echar un vistazo a: Eric Lipperts entrada de blog sobre ese tema

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top