Pergunta

Eu sempre assumiu que DBNull.Value era um solteirão. E, assim, você pode fazer coisas como esta:

VB.NET:

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

C #:

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

Mas, recentemente, eu serializado um exemplo DbNull usando o XmlSerialiser e de repente não era um solteirão mais. operações de comparação tipo (como 's (obj é DBNull) C #) trabalho OK embora.

código a seguir:

[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 que é este o caso? E como isso acontece? E isso pode acontecer com quaisquer outros campos estáticos?

PS: Estou ciente do exemplo de código VB está fazendo uma comparação de referência e c # está chamando Object.Equals. Ambos têm o mesmo comportamento com DBNull. Eu costumo trabalhar com VB.

Foi útil?

Solução

Embora DBNull.Value é um static readonly e só existe como uma única instância ... quando você de-serialize, o código de serialização seria a criação de uma nova instância do DBNull classe a partir dos dados "no fluxo. Desde o DBNull.Value é simplesmente uma instância DBNull, não há nenhuma maneira para serialização de saber que é uma instância de 'especial'.

NOTA:
Pela mesma razão, se você fizer sua própria classe com uma instância 'solteirão' que você serializar e depois de-serialize você vai obter exatamente o mesmo comportamento. Embora a instância desserializada será indistinguível da instância original, eles não serão a mesma instância .

Outras dicas

O seu código c # não é igual a chamar o método .Equals. Sem ter testado Im realmente muito certo se você Substituição

someObject == DbNull.Value

com

DbNull.Value.Equals(someObject) 

que lhe daria o resultado esperado. Para algumas entranhas sobre o operador de igualdade e o método Equals dar uma olhada: Eric Lipperts post sobre esse assunto

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top