C # objeto não é nulo, mas (myObject! = Null) ainda retornar falso
Pergunta
Eu preciso fazer um comparaison entre um objeto e NULL. Quando o objeto não é NULL eu preenchê-lo com alguns dados.
Aqui está o código:
if (region != null)
{
....
}
Isso está funcionando, mas quando looping e looping em algum momento o objeto região não é nulo (eu posso ver os dados dentro dele no modo de depuração). No passo-a-passo quando a depuração, ele não ir para dentro da instrução IF ... Quando eu faço um relógio rápido com estes seguinte expressão: eu vejo o (região == null) false retorno, E (região = null ) return false também ... por que e como?
Atualizar
ponto Alguém que o objeto era == e = sobrecarregado:
public static bool operator ==(Region r1, Region r2)
{
if (object.ReferenceEquals(r1, null))
{
return false;
}
if (object.ReferenceEquals(r2, null))
{
return false;
}
return (r1.Cmr.CompareTo(r2.Cmr) == 0 && r1.Id == r2.Id);
}
public static bool operator !=(Region r1, Region r2)
{
if (object.ReferenceEquals(r1, null))
{
return false;
}
if (object.ReferenceEquals(r2, null))
{
return false;
}
return (r1.Cmr.CompareTo(r2.Cmr) != 0 || r1.Id != r2.Id);
}
Solução
É o == e / ou! = Operador sobrecarregado para a classe do objeto região?
Agora que você já postou o código para as sobrecargas:
As sobrecargas provavelmente deve ter a seguinte aparência (código retirado lançamentos feitos por Jon Skeet e Philip Rieck ):
public static bool operator ==(Region r1, Region r2)
{
if (object.ReferenceEquals( r1, r2)) {
// handles if both are null as well as object identity
return true;
}
if ((object)r1 == null || (object)r2 == null)
{
return false;
}
return (r1.Cmr.CompareTo(r2.Cmr) == 0 && r1.Id == r2.Id);
}
public static bool operator !=(Region r1, Region r2)
{
return !(r1 == r2);
}
Outras dicas
Esses sobrecargas de operador estão quebrados.
Em primeiro lugar, torna a vida muito mais fácil se! = É implementado por apenas chamando == e invertendo o resultado.
Em segundo lugar, antes de os controlos de nulidade em == deve haver:
if (object.ReferenceEquals(r1, r2))
{
return true;
}
Ambos os sobrecargas são incorretos
public static bool operator ==(Region r1, Region r2)
{
if (object.ReferenceEquals(r1, null))
{
return false;
}
if (object.ReferenceEquals(r2, null))
{
return false;
}
return (r1.Cmr.CompareTo(r2.Cmr) == 0 && r1.Id == r2.Id);
}
Se R1 e R2 são nulos, o primeiro teste ( Object.ReferenceEquals (R1, null) ) irá retornar falso, mesmo que r2 é também nulo.
try
//ifs expanded a bit for readability
public static bool operator ==(Region r1, Region r2)
{
if( (object)r1 == null && (object)r2 == null)
{
return true;
}
if( (object)r1 == null || (object)r2 == null)
{
return false;
}
//btw - a quick shortcut here is also object.ReferenceEquals(r1, r2)
return (r1.Cmr.CompareTo(r2.Cmr) == 0 && r1.Id == r2.Id);
}
Isto às vezes pode acontecer quando você tem vários segmentos que trabalham com os mesmos dados. Se este for o caso, você pode usar um bloqueio para impedi-los de brincar uns com os outros.
Para comparação de igualdade de um tipo "T", sobrecarregar estes métodos:
int GetHashCode() //Overrides Object.GetHashCode
bool Equals(object other) //Overrides Object.Equals; would correspond to IEquatable, if such an interface existed
bool Equals(T other) //Implements IEquatable<T>; do this for each T you want to compare to
static bool operator ==(T x, T y)
static bool operator !=(T x, T y)
O seu código de comparação de tipo específico deve ser feito em um lugar : a interface IEquatable<T>
método Equals(T other)
tipo seguro.
Se você está comparando a outro tipo (T2), implementar IEquatable<T2>
bem, e colocar o código de comparação de campo para esse tipo de Equals (T2 outro).
Todos os métodos sobrecarregados e os operadores devem encaminhar a tarefa de comparação de igualdade com as principais Equals tipo seguro (T outro) método de instância, de tal forma que uma hierarquia de dependência limpa é mantida e garantias mais rigorosas são introduzidas em cada nível para eliminar a redundância e complexidade não essencial .
bool Equals(object other)
{
if (other is T) //replicate this for each IEquatable<T2>, IEquatable<T3>, etc. you may implement
return Equals( (T)other) ); //forward to IEquatable<T> implementation
return false; //other is null or cannot be compared to this instance; therefore it is not equal
}
bool Equals(T other)
{
if ((object)other == null) //cast to object for reference equality comparison, or use object.ReferenceEquals
return false;
//if ((object)other == this) //possible performance boost, ONLY if object instance is frequently compared to itself! otherwise it's just an extra useless check
//return true;
return field1.Equals( other.field1 ) &&
field2.Equals( other.field2 ); //compare type fields to determine equality
}
public static bool operator ==( T x, T y )
{
if ((object)x != null) //cast to object for reference equality comparison, or use object.ReferenceEquals
return x.Equals( y ); //forward to type-safe Equals on non-null instance x
if ((object)y != null)
return false; //x was null, y is not null
return true; //both null
}
public static bool operator !=( T x, T y )
{
if ((object)x != null)
return !x.Equals( y ); //forward to type-safe Equals on non-null instance x
if ((object)y != null)
return true; //x was null, y is not null
return false; //both null
}
Discussão:
A aplicação anterior centraliza a comparação de tipo específico (isto é, a igualdade de campo) para o final da execução IEquatable<T>
para o tipo.
Os operadores ==
e !=
ter uma implementação paralela mas oposta. Eu prefiro este por ter uma referência a outra, de modo que há uma chamada de método extra para o dependente. Se o operador !=
é simplesmente vai chamar o operador ==
, em vez de oferecer um operador igualmente realizar, então você pode também apenas usar !(obj1 == obj2)
e evitar a chamada de método extra.
A comparação-se auto é deixado de fora do operador e as implementações IEquatable<T>
iguais, porque pode introduzir 1. sobrecarga desnecessária em alguns casos, e / ou 2. desempenho inconsistente dependendo de quantas vezes uma instância é comparado a si vs outras instâncias .
Uma alternativa que eu não gosto, mas deve mencionar, é reverter essa configuração, centralizando o código de igualdade de tipo específico no operador de igualdade vez e ter a Igual métodos dependem disso. Pode-se então utilizar o atalho de ReferenceEquals(obj1,obj2)
para verificar se há igualdade de referência e igualdade nula simultaneamente como Philip mencionado em um post anterior, mas essa ideia é enganosa. Parece que você está matando dois pássaros com uma pedra, mas a sua realmente criar mais trabalho - depois de determinar os objetos não são nem tanto nulo nem a mesma instância, então você vai, além disso, ainda tem que para verificar se cada instância é nulo. Na minha aplicação, você verificar para qualquer única instância ser nulo exatamente uma vez. No momento em que o método de instância é chamado Igual, ele já está descartado que o primeiro objeto a ser comparado é nulo, então tudo o que resta a fazer é verificar se o outro é nulo. Então, depois de, no máximo, duas comparações, nós saltar directamente para a verificação de campo, não importa qual o método que usamos (Equals(object),Equals(T),==,!=
). Além disso, como já referi, se você realmente está comparando e objeto para si a maior parte do tempo, então você poderia acrescentar que o check-in o método Equals apenas antes de mergulhar nas comparações de campo. O ponto em adicionando-o último é que você ainda pode manter a hierarquia de fluxo / dependência sem a introdução de um redundante / verificação inútil em todos os níveis.
Assim é que estas verificações aqui não está certo:
public static bool operator !=(Region r1, Region r2)
{
if (object.ReferenceEquals(r1, null))
{
return false;
}
if (object.ReferenceEquals(r2, null))
{
return false;
}
...
Há uma outra possibilidade de que você precisa clicar no ícone de atualização ao lado do parâmetro que você está assistindo. VS tentar manter-se com o desempenho enquanto não avaliar cada declaração / parâmetro. Dê uma olhada para se certificar, antes de começar a fazer mudanças para lugares que Non relevante.
bool comp;
if (object.IsNullOrEmpty(r1))
{
comp = false;
}
if (object.IsNullOrEmpty(r2))
{
comp = false;
}
return comp;