Considere este código:
int age = 25;
short newAge = 25;
Console.WriteLine(age == newAge); //true
Console.WriteLine(newAge.Equals(age)); //false
Console.ReadLine();
Ambos int
e short
são tipos primitivos, mas uma comparação com ==
retornos verdadeiro e uma comparação com Equals
retornos falsos.
Por quê?
Console.WriteLine(age.Equals(newAge));
Equals()
é em geral.Respostas:
Resposta curta:
A igualdade é complicada.
Resposta detalhada:
Os tipos de primitivas substituem a base
object.Equals(object)
e retornam true se a caixaobject
for do mesmo tipo e valor. (Observe que ele também funcionará para tipos anuláveis; os tipos anuláveis não nulos sempre se encaixam em uma instância do tipo subjacente.)Como
newAge
é ashort
, seuEquals(object)
método só retornará true se você passar um short in a box com o mesmo valor. Você está passando um in a boxint
, então ele retorna false.Por outro lado, o
==
operador é definido como tendo doisint
s (oushort
s oulong
s).Quando você o chama com an
int
e ashort
, o compilador converte implicitamente oshort
emint
e compara osint
s resultantes pelo valor.Outras maneiras de fazê-lo funcionar
Os tipos primitivos também têm seu próprio
Equals()
método que aceita o mesmo tipo.Se você escrever
age.Equals(newAge)
, o compilador selecionaráint.Equals(int)
a melhor sobrecarga e converterá implicitamenteshort
emint
. Ele retornarátrue
, pois esse método simplesmente compara osint
s diretamente.short
também possui umshort.Equals(short)
método, masint
não pode ser convertido implicitamente emshort
, portanto você não está chamando.Você pode forçá-lo a chamar esse método com uma conversão:
Isso chamará
short.Equals(short)
diretamente, sem boxe. Seage
for maior que 32767, lançará uma exceção de estouro.Você também pode chamar a
short.Equals(object)
sobrecarga, mas passar explicitamente um objeto em caixa para que ele obtenha o mesmo tipo:Como a alternativa anterior, isso provocará um estouro se não couber em a
short
. Ao contrário da solução anterior, ele encaixotará oshort
objeto em um objeto, desperdiçando tempo e memória.Código fonte:
Aqui estão os dois
Equals()
métodos do código-fonte real:Leitura adicional:
Veja Eric Lippert .
fonte
long == int
,int
implicitamente convertido para along
direita?int age = 25;
paraconst int age = 25;
, o resultado será alterado. Isso ocorre porque uma conversão implícita deint
parashort
existe nesse caso. Consulte Conversões implícitas de expressão constante .==
compara tipos de referência por referência. Para tipos de valor e tipos que sobrecarregam==
, isso não ocorre.Porque não há sobrecarga para
short.Equals
que aceita umint
. Portanto, isso é chamado:obj
não é umshort
.. portanto, é falso.fonte
Quando você passa
int
parashort
igual a, você passaobject
:Portanto, esse pseudocódigo é executado:
fonte
Para tipos de valor,
.Equals
requer que os dois objetos sejam do mesmo tipo e tenham o mesmo valor, enquanto==
apenas testa se os dois valores são iguais.Object.Equals
http://msdn.microsoft.com/en-us/library/bsc2ak47(v=vs.110).aspx
fonte
==
é usado para verificar uma condição igual, pode ser considerado um operador (operador booleano), apenas para comparar duas coisas e aqui o tipo de dados não importa, pois haveria uma conversão de tipo feita eEquals
também é usado para verificar condições iguais , mas nesse caso os tipos de dados devem ser os mesmos. N Equals é um método, não um operador.Abaixo está um pequeno exemplo do que você forneceu e isso esclarecerá a diferença em breve.
no exemplo acima, X e Y têm os mesmos valores, ou seja, 1 e, quando usamos
==
, ele retornará true, como no caso de==
, o tipo curto é convertido em int pelo compilador e o resultado é fornecido.e quando usamos
Equals
, a comparação é feita, mas a conversão de tipo não é feita pelo compilador, então falso é retornado.Gente, por favor me avise se eu estiver errado.
fonte
Em muitos contextos em que um método ou argumento de operador não é do tipo necessário, o compilador C # tentará executar uma conversão implícita de tipo. Se o compilador puder fazer com que todos os argumentos satisfaçam seus operadores e métodos adicionando conversões implícitas, ele o fará sem reclamar, embora em alguns casos (especialmente com testes de igualdade!) Os resultados possam ser surpreendentes.
Além disso, cada tipo de valor como
int
oushort
realmente descreve um tipo de valor e um tipo de objeto (*). Existem conversões implícitas para converter valores em outros tipos de valores e converter qualquer tipo de valor em seu tipo de objeto correspondente, mas os diferentes tipos de objetos não são implicitamente conversíveis entre si.Se alguém usa o
==
operador para comparar umshort
e umint
, oshort
será convertido implicitamente a umint
. Se o seu valor numérico for igual ao valor deint
, o valorint
para o qual foi convertido será igual ao valorint
de comparação. Se alguém tentar usar oEquals
método no short para compará-lo com umint
, no entanto, a única conversão implícita que satisfaria uma sobrecarga doEquals
método seria a conversão para o tipo de objeto correspondente aint
. Quandoshort
perguntado se ele corresponde ao objeto transmitido, ele observará que o objeto em questão é umint
e não umshort
e, portanto, concluirá que ele não pode ser igual.Em geral, embora o compilador não se queixe, deve-se evitar comparar coisas que não são do mesmo tipo; se alguém estiver interessado em saber se a conversão de coisas em uma forma comum daria o mesmo resultado, deve-se realizar essa conversão explicitamente. Considere, por exemplo,
Existem três maneiras pelas quais se pode comparar um
int
a umfloat
. Alguém pode querer saber:float
valor mais próximo possível daint
correspondência éfloat
?float
correspondênciaint
?int
efloat
represente o mesmo valor numérico.Se alguém tentar comparar um
int
efloat
diretamente, o código compilado responderá à primeira pergunta; se é isso que o programador pretendia, no entanto, estará longe de ser óbvio. Alterar a comparação para(float)i == f
deixaria claro que o primeiro significado era intencional ou(double)i == (double)f
faria com que o código respondesse à terceira pergunta (e deixasse claro que era o que pretendia).(*) Mesmo que a especificação C # considere um valor do tipo, por exemplo,
System.Int32
como um objeto do tipoSystem.Int32
, essa visão é contrariada pelo requisito de que um código seja executado em uma plataforma cuja especificação considere valores e objetos como habitando universos diferentes. Além disso, seT
é um tipo de referência ex
é aT
, uma referência do tipoT
deve poder fazer referênciax
. Assim, se uma variávelv
do tipoInt32
contiver umObject
, uma referência do tipoObject
deve poder manter uma referênciav
ou seu conteúdo. De fato, uma referência do tipoObject
seria capaz de apontar para um objeto contendo dados copiadosv
, mas não parav
si próprio nem para seu conteúdo. Isso sugeriria que nemv
nem seu conteúdo é realmente umObject
.fonte
the only implicit conversion which would satisfy an overload of the Equals method would be the conversion to the object type corresponding to int
Errado. Ao contrário do Java, o C # não possui tipos primitivos e em caixa separados. Ele está sendo encaixotadoobject
porque é a única outra sobrecarga deEquals()
.float
. A conversão de afloat
para adouble
não criará magicamente nova precisão.List<String>.Enumerator
e um objeto de pilha do tipoList<String>.Enumerator
é o mesmo, mas a especificação do ECMA / CLI diz que são diferentes e, mesmo quando usados no C #, se comportam de maneira diferente.i
ef
cada um deles foi convertidodouble
antes da comparação, eles renderiam 16777217.0 e 16777216.0, que são comparados como desiguais. A conversãoi
float
renderia 16777216.0f, comparando igual af
.bool SelfSame<T>(T p) { return Object.ReferenceEquals((Object)p,(Object)p);}
. O tipo de objeto em caixa correspondente a um tipo de valor pode satisfazer o tipo de parâmetroReferenceEquals
via uma upcast de preservação de identidade ; o tipo de local de armazenamento, no entanto, requer uma conversão sem preservação de identidade . Se converter umT
paraU
produz uma referência a algo diferente do originalT
, isso sugere que aT
não é realmente umU
.Equals () é um método da sintaxe da classe System.Object
: bool virtual virtual Equals ()
Recomendação se quisermos comparar o estado de dois objetos, devemos usar o método Equals ()
como indicado acima respostas == operadores comparam os valores são os mesmos.
Por favor, não se confunda com o ReferenceEqual
Referência Equals ()
Sintaxe: public static bool ReferenceEquals ()
Determina se a instância de objetos especificada é da mesma instância
fonte
O que você precisa entender é que fazer
==
sempre acabará chamando um método. A questão é se ligar==
eEquals
acaba ligando / fazendo as mesmas coisas.Com os tipos de referência,
==
sempre verificará primeiro se as referências são iguais (Object.ReferenceEquals
).Equals
por outro lado, pode ser substituído e pode verificar se alguns valores são iguais.EDIT: para responder svick e adicionar comentário SLaks, aqui está um código IL
fonte
int
s com == chama? Dica: não existe umoperator ==
método paraInt32
, mas existe um paraString
.==
isso não apenas faz mágica, mas simplesmente chama um método (a maioria dos programadores provavelmente nunca implementou / substituiu qualquer operador). Talvez eu pudesse ter adicionado um comentário à sua pergunta em vez de adicionar minha própria resposta. Sinta-se à vontade para atualizar o seu se achar que o que eu disse é relevante.==
nos tipos primitivos não é um operador sobrecarregado, mas um recurso de linguagem intrínseca que é compilado com aceq
instrução IL.== No Primitivo
Na comparação primitiva, o operador == se comporta bastante óbvio; em C # existem muitos == sobrecarga do operador disponível.
Portanto, neste caso, não há conversão implícita de
int
parashort
masshort
paraint
é possível. Portanto, newAge é convertido em int e ocorre uma comparação que retorna true, pois ambos mantêm o mesmo valor. Portanto, é equivalente a:.Equals () em Primitivo
Aqui precisamos ver o que é o método Equals (), chamando Equals com uma variável de tipo curto. Portanto, existem três possibilidades:
O primeiro tipo não é o caso aqui, pois o número de argumentos é diferente, chamando com apenas um argumento do tipo int. O terceiro também é eliminado, como mencionado acima, a conversão implícita de int para short não é possível. Então aqui o segundo tipo de
Equals(object)
é chamado. Oshort.Equals(object)
é:Portanto, aqui a condição foi testada,
z is short
que é falsa, pois z é um int e, portanto, retorna falso.Aqui está um artigo detalhado de Eric Lippert
fonte