Eu tenho uma condição em um aplicativo silverlight que compara duas strings, por algum motivo, quando eu o uso ==
, retorna false enquanto .Equals()
retorna true .
Aqui está o código:
if (((ListBoxItem)lstBaseMenu.SelectedItem).Content.Equals("Energy Attack"))
{
// Execute code
}
if (((ListBoxItem)lstBaseMenu.SelectedItem).Content == "Energy Attack")
{
// Execute code
}
Alguma razão para isso estar acontecendo?
==
, mas os operadores não são polimórficos. Nesse código, o==
operador é chamado no tipoobject
, que faz uma comparação de identidade em vez de um valor um.==
sobrecarga com base no tipo de tempo de compilação dos operandos. AContent
propriedade éobject
. Os operadores não são virtuais, portanto, a implementação padrão de==
é chamada, fornecendo uma comparação de igualdade de referência. Com Igual, a chamada vai para o método virtualobject.Equals(object)
;string
substitui esse método e executa uma comparação ordinal no conteúdo da string. Consulte msdn.microsoft.com/en-us/library/fkfd9eh8(v=vs.110).aspx e referenceource.microsoft.com/#mscorlib/system/string.cs.507 .==
tem tempo de compilaçãoobject
e o lado direitostring
, o tipo do tempo de compilação , o compilador C # deve selecionar a sobrecarga (problemática, neste caso)operator ==(object, object)
; mas vai emitir um aviso de tempo de compilação que poderia ser não intencional. Então leia os avisos em tempo de compilação! Para corrigir o problema e ainda usar==
, gire o lado esquerdo parastring
. Se bem me lembro, o texto de aviso sugere exatamente isso.Respostas:
Quando
==
é usado em uma expressão do tipoobject
, será resolvido comoSystem.Object.ReferenceEquals
.Equals
é apenas umvirtual
método e se comporta como tal; portanto, a versão substituída será usada (que, para ostring
tipo, compara o conteúdo).fonte
object
tipo (observe a fonte monoespaçada) é tecnicamente destinado a ser "uma expressão do tipoSystem.Object
". Não tem nada a ver com o tipo de tempo de execução da instância que é referida pela expressão. Eu acho que a afirmação "operadores definidos pelo usuário são tratados comovirtual
métodos" é extremamente enganosa. Eles são tratados como métodos sobrecarregados e dependem apenas do tipo de tempo de compilação dos operandos. De fato, após o conjunto de operadores definidos pelo usuário candidatos é calculado, o resto do procedimento de ligação será exatamente o algoritmo de resolução de sobrecarga de métodovirtual
resolução do método depende do tipo de tempo de execução real de uma instância, enquanto isso é completamente ignorado na resolução de sobrecarga do operador, e esse é realmente o ponto principal da minha resposta.Ao comparar uma referência de objeto a uma sequência de caracteres (mesmo que a referência de objeto se refira a uma sequência de caracteres), o comportamento especial do
==
operador específico da classe de sequência é ignorado.Normalmente (quando não estiver lidando com seqüências de caracteres, isto é),
Equals
compara valores , enquanto==
compara referências de objetos . Se dois objetos que você está comparando estão se referindo à mesma instância exata de um objeto, ambos retornam true, mas se um tiver o mesmo conteúdo e vier de uma fonte diferente (é uma instância separada com os mesmos dados), apenas Igual será retornar verdadeiro. No entanto, como observado nos comentários, string é um caso especial, porque substitui o==
operador, de modo que, ao lidar exclusivamente com referências de string (e não referências a objetos), apenas os valores são comparados, mesmo que sejam instâncias separadas. O código a seguir ilustra as diferenças sutis nos comportamentos:A saída é:
fonte
==
e.Equals
ambos dependem do comportamento definido no tipo real e no tipo real no site da chamada. Ambos são apenas métodos / operadores que podem ser substituídos em qualquer tipo e com qualquer comportamento que o autor desejar. Na minha experiência, acho que é comum as pessoas implementarem.Equals
em um objeto, mas negligenciam a implementação do operador==
. Isso significa que.Equals
realmente medirá a igualdade dos valores, enquanto==
medirá se eles são ou não a mesma referência.Quando estou trabalhando com um novo tipo cuja definição está em fluxo ou escrevendo algoritmos genéricos, acho que a melhor prática é a seguinte
Object.ReferenceEquals
diretamente (não é necessário no caso genérico)EqualityComparer<T>.Default
Em alguns casos, quando sinto que o uso de
==
é ambíguo, explicitamente utilizareiObject.Reference
iguais no código para remover a ambiguidade.Eric Lippert publicou recentemente um post no blog sobre o motivo de haver dois métodos de igualdade no CLR. Vale a pena ler
fonte
== Operador
.É igual a
fonte
==
operador pode ser sobrecarregado para qualquer tipo, não apenas para string. A descrição de uma exceção de caso especial apenas para cadeia de caracteres representa incorretamente a semântica do operador. Seria mais preciso, embora talvez não seja muito útil, dizer "se os operandos são tipos de referência, eles retornam true se os operandos se referem ao mesmo objeto, a menos que haja uma sobrecarga aplicável; nesse caso, a implementação dessa sobrecarga determina o resultado. " O mesmo aconteceEquals
com a complicação adicional de ser um método virtual, para que seu comportamento possa ser substituído e sobrecarregado.Em primeiro lugar, não é uma diferença. Para números
E para cordas
Nos dois casos,
==
comporta-se de maneira mais útil do que.Equals
fonte
==
operador. Por exemplo, 16777216.0f deve ser igual (int) 16777217, (duplo) 16777217.0, ambos ou nenhum? As comparações entre tipos integrais são boas, mas as comparações de ponto flutuante só devem ser realizadas IMHO com valores explicitamente convertidos em tipos correspondentes. A comparação de afloat
com algo que não seja afloat
, ou adouble
com algo que não seja adouble
, me parece um cheiro de código principal que não deve ser compilado sem diagnóstico.x == y
isso não impliquex/3 == y/3
(tentex = 5
ey = 5.0
)./
para a divisão inteira um defeito no design de C # e Java. Pascaldiv
e até VB.NET` are much better. The problems with
== `são piores, no entanto:x==y
ey==z
não implica issox==z
(considere os três números no meu comentário anterior). Quanto à relação que você sugere, mesmo sex
ey
são ambosfloat
ou ambosdouble
,x.equals((Object)y)
não implica que1.0f/x ==
1,0f / y` (se eu tivesse meus druthers, isso garantiria que; mesmo==
que não distinga positivo e zero,Equals
deveria).Tanto quanto eu entendo, a resposta é simples:
==
compara referências de objetos..Equals
compara o conteúdo do objeto.String
tipos de dados sempre agem como comparação de conteúdo.Espero estar correto e que tenha respondido sua pergunta.
fonte
Eu acrescentaria que, se você converter seu objeto em uma string, ele funcionará corretamente. É por isso que o compilador emitirá um aviso dizendo:
fonte
object expr = XXX; if (expr == "Energy") { ... }
, como o lado esquerdo é do tipo em tempo de compilaçãoobject
, o compilador precisa usar a sobrecargaoperator ==(object, object)
. Ele verifica a igualdade de referência. Se isso darátrue
oufalse
pode ser difícil de prever devido à internação de strings . Se você souber que o lado esquerdo énull
do tipo oustring
, gire o lado esquerdo parastring
antes de usar==
.Como a versão estática do
.Equal
método não foi mencionada até agora, gostaria de adicioná-lo aqui para resumir e comparar as três variações.onde
MyString
é uma variável que vem de outro lugar no código.Informações de plano de fundo e para o verão:
Em Java, usar
==
para comparar seqüências de caracteres não deve ser usado. Menciono isso no caso de você precisar usar os dois idiomas e também informar que o uso de==
também pode ser substituído por algo melhor em C #.No C #, não há diferença prática para comparar seqüências de caracteres usando o Método 1 ou 2, desde que ambas sejam do tipo seqüência de caracteres. No entanto, se um é nulo, outro de outro tipo (como um número inteiro) ou um objeto que possui uma referência diferente, como mostra a pergunta inicial, você pode experimentar que comparar o conteúdo por igualdade pode não retornar o que você espera.
Solução sugerida:
Como o uso
==
não é exatamente o mesmo que o da.Equals
comparação, você pode usar o método estático String.Equals . Dessa forma, se os dois lados não forem do mesmo tipo, você ainda comparará o conteúdo e se um for nulo, evitará a exceção.É um pouco mais para escrever, mas na minha opinião, mais seguro de usar.
Aqui estão algumas informações copiadas da Microsoft:
Parâmetros
a
CordaA primeira string a comparar, ou
null
.b
CordaA segunda string para comparar, ou
null
.Devoluções
Boolean
true
se o valor dea
for o mesmo que o valor deb
; caso contráriofalse
,. Se ambosa
eb
sãonull
, o método retornatrue
.fonte
Apenas como uma adição às respostas já boas: Esse comportamento NÃO se limita a Strings ou compara diferentes tipos de número. Mesmo se os dois elementos forem do tipo objeto do mesmo tipo subjacente. "==" não funcionará.
A captura de tela a seguir mostra os resultados da comparação de dois objetos {int} - valores
fonte
Estou um pouco confuso aqui. Se o tipo de conteúdo do tempo de execução for do tipo string, ambos == e Equals deverão retornar true. No entanto, como esse não parece ser o caso, o tipo de conteúdo em tempo de execução não é uma string e chamar Equals está fazendo uma igualdade referencial e isso explica por que Equals ("Energy Attack") falha. No entanto, no segundo caso, a decisão sobre qual operador == estático sobrecarregado deve ser chamado é tomada em tempo de compilação e essa decisão parece ser == (string, string). isso sugere que o conteúdo fornece uma conversão implícita em string.
fonte
Há uma outra dimensão na resposta anterior de @BlueMonkMN. A dimensão adicional é que a resposta à pergunta do título do @ Drahcir, como é afirmada, também depende de como chegamos ao
string
valor. Ilustrar:A saída é:
fonte
Adicionando mais um ponto à resposta.
.EqualsTo()
O método fornece provisão para comparar com a cultura e diferencia maiúsculas de minúsculas.fonte
O
==
token no C # é usado para dois operadores diferentes de verificação de igualdade. Quando o compilador encontra esse token, ele verifica se um dos tipos comparados implementou uma sobrecarga de operador de igualdade para os tipos de combinação específicos que estão sendo comparados (*) ou para uma combinação de tipos nos quais os dois tipos podem ser convertidos. Se o compilador encontrar uma sobrecarga, ele a utilizará. Caso contrário, se os dois tipos são de referência e não são classes não relacionadas (podem ser uma interface ou podem ser classes relacionadas), o compilador considerará==
um operador de comparação de referência. Se nenhuma das condições se aplicar, a compilação falhará.Observe que alguns outros idiomas usam tokens separados para os dois operadores de verificação de igualdade. No VB.NET, por exemplo, o
=
token é usado em expressões exclusivamente para o operador de verificação de igualdade sobrecarregável eIs
é usado como operador de teste de referência ou teste nulo. Um uso=
em um tipo que não substitui o operador de verificação de igualdade falhará, assim como a tentativa de usarIs
para qualquer outro propósito que não seja testar a igualdade ou a nulidade de referência.(*) Os tipos geralmente sobrecarregam a igualdade apenas para comparação com eles mesmos, mas pode ser útil para os tipos sobrecarregar o operador de igualdade para comparação com outros tipos específicos; por exemplo,
int
poderia ter (e o IMHO deveria ter, mas não definiu) operadores de igualdade para comparação comfloat
, para que 16777217 não se reportasse igual a 16777216f. Como é, como esse operador não está definido, o C # promoverá oint
tofloat
, arredondando-o para 16777216f antes que o operador de verificação de igualdade o veja; esse operador então vê dois números iguais de ponto flutuante e os informa como iguais, sem saber do arredondamento ocorrido.fonte
3
como sendo igual a3.0f
. Se exigirmos que o programador diga o que se pretende em todos os casos, não há risco de comportamento padrão levar a resultados indesejados, pois não há comportamento padrão.Respostas e exemplos realmente ótimos!
Gostaria apenas de acrescentar a diferença fundamental entre os dois,
Com esse conceito em mente, se você elaborar algum exemplo (olhando para o tipo de referência à esquerda e à direita e verificando / sabendo se o tipo realmente tem == operador sobrecarregado e igual a superação), você certamente encontrará a resposta certa .
fonte
Quando criamos qualquer objeto, existem duas partes no objeto, uma é o conteúdo e a outra é a referência a esse conteúdo.
==
compara conteúdo e referência;equals()
compara apenas o conteúdohttp://www.codeproject.com/Articles/584128/What-is-the-difference-between-equalsequals-and-Eq
fonte
a
eb
são referências de seqüência de caracteres, o resultado dea == b
não depende se as referências apontam para o mesmo objeto.==
O operador == pode ser usado para comparar duas variáveis de qualquer tipo e simplesmente compara os bits .
Nota: existem mais zeros no lado esquerdo do int, mas não nos importamos com isso aqui.
int a (00000011) == byte b (00000011)
Lembre-se de que o operador se preocupa apenas com o padrão dos bits na variável.
Use == Se duas referências (primitivas) se referirem ao mesmo objeto no heap.
As regras são as mesmas, independentemente de a variável ser uma referência ou primitiva.
a == c é verdadeiro a == b é falso
o padrão de bits é o mesmo para a e c, portanto são iguais usando ==.
Igual():
Use o método equals () para ver se dois objetos diferentes são iguais .
Como dois objetos String diferentes que representam os caracteres em "Jane"
fonte
object a = 3; object b = 3; Console.WriteLine(a == b);
. A saída é falsa, mesmo que os padrões de bits dos valores sejam os mesmos. Os tipos dos operandos também são importantes. A razão pela qual "não nos importamos" com o número diferente de zeros no seu exemplo é que, quando chamamos o operador igual, o número de zeros é realmente o mesmo , devido à conversão implícita.A única diferença entre Igual e == está na comparação do tipo de objeto. em outros casos, como tipos de referência e tipos de valor, eles são quase os mesmos (ambos são igualdade de bits ou ambos são igualdade de referência).
objeto: Equals: igualdade bit a bit ==: igualdade de referência
string: (iguais e == são iguais para string, mas se uma das string for alterada para objeto, o resultado da comparação será diferente) Igual a: igualdade de bits ==: igualdade de bits
Veja aqui para mais explicações.
fonte