Domanda

Ho sempre pensato che DBNull.Value era un Singleton. E così si potrebbe fare cose come questa:

VB.NET:

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

C #:

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

Ma di recente, ho serializzato un'istanza DBNull utilizzando il XmlSerialiser e improvvisamente non era un singleton più. operazioni di confronto di tipo (come C # 's (obj è DBNull)) funzionano OK però.

Codice segue:

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

}

Perché è questo il caso? E come è successo? E può accadere con altri campi statici?

PS: Sono consapevole di codice VB sta facendo un confronto di riferimento e C # sta chiamando Object.Equals. Entrambi hanno lo stesso comportamento con DBNull. Di solito lavoro con VB.

È stato utile?

Soluzione

Anche se è un DBNull.Value static readonly ed esiste solo come una singola istanza ... quando si de-serialize, il codice di serializzazione sarebbe la creazione di una nuova istanza della classe dalla DBNull 'data' nel flusso. Dal momento che il DBNull.Value è semplicemente un esempio DBNull, non c'è modo per la serializzazione di sapere che si tratta di un'istanza 'speciale'.

Nota:
Per lo stesso motivo, se si effettua la propria classe con un'istanza 'Singleton' che si serializzare e quindi de-serializzare si ottiene esattamente lo stesso comportamento. Anche se l'istanza deserializzato non sarà diversa dal l'istanza originale, non saranno la stessa istanza .

Altri suggerimenti

Il codice C # non è uguale chiamando il metodo .equals. Con cui dover testato Im in realtà piuttosto sicuro se si sostituisse

someObject == DbNull.Value

con

DbNull.Value.Equals(someObject) 

si darebbe il risultato atteso. Per alcune parti interne sul operatore di uguaglianza e il metodo Equals dare un'occhiata a: Eric Lipperts post sul blog su questo argomento

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top