Рассмотрим этот код:
int age = 25;
short newAge = 25;
Console.WriteLine(age == newAge); //true
Console.WriteLine(newAge.Equals(age)); //false
Console.ReadLine();
Оба int
и short
являются примитивными типами, но сравнение с ==
возвращает true, а сравнение с Equals
возвращает false.
Зачем?
Console.WriteLine(age.Equals(newAge));
Equals()
есть в целом.Ответы:
Короткий ответ:
Равенство сложно.
Подробный ответ:
Типы примитивов переопределяют базовые
object.Equals(object)
и возвращают истину, если упакованные в штучную упаковкуobject
имеют тот же тип и значение. (Обратите внимание, что это также будет работать для типов, допускающих значение NULL; типы, не допускающие значения NULL, всегда передаются экземпляру базового типа.)Поскольку
newAge
это ashort
, егоEquals(object)
метод возвращает true только в том случае, если вы передаете короткую коробку с тем же значением. Вы передаете коробкуint
, поэтому она возвращает false.Напротив,
==
оператор определяется как принимающий дваint
s (илиshort
s, илиlong
s).Когда вы вызываете его с
int
иshort
, компилятор неявно преобразоватьshort
вint
и сравнить полученныйint
s по значению.Другие способы заставить это работать
Примитивные типы также имеют свой собственный
Equals()
метод, который принимает тот же тип.Если вы напишете
age.Equals(newAge)
, компилятор выберетint.Equals(int)
лучшую перегрузку и неявно преобразуетshort
вint
. Затем он вернетсяtrue
, поскольку этот метод просто сравниваетint
s напрямую.short
также естьshort.Equals(short)
метод, ноint
не может быть неявно преобразован вshort
, поэтому вы его не вызываете.Вы можете заставить его вызвать этот метод с помощью приведения:
Console.WriteLine(newAge.Equals((short)age)); // true
Это вызовет
short.Equals(short)
напрямую, без бокса. Еслиage
больше 32767, будет выдано исключение переполнения.Вы также можете позвонить в
short.Equals(object)
перегрузку, но явно передать упакованный объект, чтобы он получил тот же тип:Console.WriteLine(newAge.Equals((object)(short)age)); // true
Как и предыдущая альтернатива, это вызовет переполнение, если оно не помещается в
short
. В отличие от предыдущего решения, оно помещаетshort
объект в объект, тратя время и память.Исходный код:
Вот оба
Equals()
метода из реального исходного кода:public override bool Equals(Object obj) { if (!(obj is Int16)) { return false; } return m_value == ((Int16)obj).m_value; } public bool Equals(Int16 obj) { return m_value == obj; }
Дальнейшее чтение:
См. Эрика Липперта .
источник
long == int
,int
неявно преобразован вlong
правый?int age = 25;
наconst int age = 25;
, то результат изменится. Это происходит потому , что неявное преобразованиеint
вshort
не существует в этом случае. См. Неявные преобразования константных выражений .==
сравнивает ссылочные типы по ссылке. Для типов значений и для типов, которые перегружают==
, это не так.Потому что нет перегрузки для того,
short.Equals
чтобы приниматьint
. Поэтому это называется:public override bool Equals(object obj) { return obj is short && this == (short)obj; }
obj
это неshort
.. следовательно, это ложь.источник
Когда вы переходите
int
кshort
Equals, вы проходитеobject
:Итак, этот псевдокод работает:
return obj is short && this == (short)obj;
источник
Для типов значений
.Equals
требует , чтобы два объекта были одного типа и имели одно и то же значение, а==
просто проверяет, совпадают ли два значения.Object.Equals
http://msdn.microsoft.com/en-us/library/bsc2ak47(v=vs.110).aspx
источник
==
используется для проверки условия равенства, его можно рассматривать как оператор (логический оператор), просто чтобы сравнить 2 вещи, и здесь тип данных не имеет значения, поскольку будет выполнено приведение типа, аEquals
также используется для проверки условия равенства , но в этом случае типы данных должны быть одинаковыми. N Equals - это метод, а не оператор.Ниже приведен небольшой пример, взятый из того, который вы предоставили, и он вкратце разъяснит разницу.
int x=1; short y=1; x==y;//true y.Equals(x);//false
в приведенном выше примере X и Y имеют одинаковые значения, то есть 1, и когда мы используем
==
, он вернет истину, как в случае==
, короткий тип преобразуется компилятором в int и выдается результат.и когда мы используем
Equals
, сравнение выполняется, но преобразование типов не выполняется компилятором, поэтому возвращается false.Ребята, дайте мне знать, если я ошибаюсь.
источник
Во многих контекстах, где аргумент метода или оператора не относится к требуемому типу, компилятор C # попытается выполнить неявное преобразование типа. Если компилятор может заставить все аргументы удовлетворять свои операторы и методы, добавляя неявные преобразования, он сделает это без жалоб, даже если в некоторых случаях (особенно с тестами на равенство!) Результаты могут быть неожиданными.
Кроме того, каждый тип значения, такой как
int
илиshort
фактически, описывает как вид значения, так и вид объекта (*). Неявные преобразования существуют для преобразования значений в другие типы значений и преобразования любого значения в соответствующий ему вид объекта, но различные типы объектов не могут быть неявно преобразованы друг в друга.Если использовать
==
оператор для сравнения ashort
и anint
,short
будет неявно преобразован вint
. Если его числовое значение было равно значению, то значениеint
, вint
которое оно было преобразовано, будет равно значению,int
с которым оно сравнивается. Однако, если кто-то попытается использоватьEquals
метод на коротком отрезке, чтобы сравнить его с объектомint
, единственным неявным преобразованием, которое удовлетворяет перегрузкеEquals
метода, будет преобразование в тип объекта, соответствующийint
. Когда егоshort
спросят, соответствует ли он переданному объекту, он заметит, что рассматриваемый объект является,int
а неshort
и, таким образом выводу, что он не может быть равен.В общем, хотя компилятор не будет жаловаться на это, следует избегать сравнения вещей, которые не относятся к одному типу; если кто-то интересуется, приведет ли преобразование вещей к общей форме к тому же результату, следует выполнить такое преобразование явно. Рассмотрим, например,
int i = 16777217; float f = 16777216.0f; Console.WriteLine("{0}", i==f);
Есть три способа сравнить a
int
с afloat
. Возможно, вы захотите узнать:float
значение кint
сопрягатьfloat
?float
сопрягатьint
?int
иfloat
представляют одно и то же числовое значение.Если попытаться сравнить
int
иfloat
напрямую, скомпилированный код ответит на первый вопрос; Однако далеко не очевидно, что задумал программист. Изменение сравнения на(float)i == f
прояснит, что было предназначено первое значение, или(double)i == (double)f
заставит код ответить на третий вопрос (и прояснить, что было задумано).(*) Даже если спецификация C # рассматривает значение типа, например,
System.Int32
как объект типаSystem.Int32
, такое представление противоречит требованию, чтобы код выполнялся на платформе, спецификация которой рассматривает значения и объекты как населяющие разные вселенные. Кроме того, еслиT
это ссылочный тип, аx
- этоT
, то ссылка типаT
должна иметь возможность ссылаться наx
. Таким образом, если переменнаяv
типаInt32
содержитObject
, ссылка типаObject
должна иметь возможность содержать ссылкуv
или ее содержимое. Фактически, ссылка типаObject
может указывать на объект, содержащий скопированные данные, и его содержимое на самом деле не является .v
, но не наv
себя или его содержимое. Это предполагает, что ниv
Object
источник
the only implicit conversion which would satisfy an overload of the Equals method would be the conversion to the object type corresponding to int
Неправильно. В отличие от Java, в C # нет отдельных примитивных и упакованных типов. Его помещают в коробку,object
потому что это единственная другая перегрузкаEquals()
.float
. Преобразование afloat
в adouble
не создаст новой точности волшебным образом.List<String>.Enumerator
и объекта кучи типаList<String>.Enumerator
одинаково, но в спецификации ECMA / CLI говорится, что они разные, и даже при использовании в C # они ведут себя по-разному.i
иf
были преобразованы в каждыйdouble
до сравнения, они дали бы 16777217.0 и 16777216.0, которые сравниваются как неравные. Преобразованиеi
float
даст 16777216.0f, по сравнению сf
.bool SelfSame<T>(T p) { return Object.ReferenceEquals((Object)p,(Object)p);}
. Упакованный тип объекта, соответствующий типу значения, может удовлетворять типу параметраReferenceEquals
посредством восходящего преобразования с сохранением идентичности; однако тип места хранения требует преобразования без сохранения идентичности . Если приведениеT
кU
дает ссылку на что-то другое, кроме оригиналаT
, это подсказывает мне, что a наT
самом деле не являетсяU
.Равно () представляет собой метод System.Object класса
Синтаксиса: Общественное Equals виртуальной BOOL ()
Рекомендация , если мы хотим , чтобы сравнить состояние двух объектов , то мы должны использовать Equals () метод
как указано выше, операторы ответов == сравнивают значения одинаковы.
Пожалуйста, не путайте с ReferenceEqual
Ссылка Equals ()
Синтаксис: public static bool ReferenceEquals ()
Определяет, принадлежат ли указанные экземпляры объектов к одному экземпляру.
источник
Что вам нужно понять, так это то, что выполнение
==
всегда приводит к вызову метода. Вопрос в том, звонит ли==
и вEquals
конце концов звонит / делает то же самое.Со ссылочными типами
==
всегда сначала проверяет, совпадают ли ссылки (Object.ReferenceEquals
).Equals
с другой стороны, его можно переопределить и проверить, равны ли некоторые значения.РЕДАКТИРОВАТЬ: чтобы ответить на svick и добавить комментарий SLaks, вот некоторый код IL
int i1 = 0x22; // ldc.i4.s ie pushes an int32 on the stack int i2 = 0x33; // ldc.i4.s short s1 = 0x11; // ldc.i4.s (same as for int32) short s2 = 0x22; // ldc.i4.s s1 == i1 // ceq i1 == s1 // ceq i1 == i2 // ceq s1 == s2 // ceq // no difference between int and short for those 4 cases, // anyway the shorts are pushed as integers. i1.Equals(i2) // calls System.Int32.Equals s1.Equals(s2) // calls System.Int16.Equals i1.Equals(s1) // calls System.Int32.Equals: s1 is considered as an integer // - again it was pushed as such on the stack) s1.Equals(i1) // boxes the int32 then calls System.Int16.Equals // - int16 has 2 Equals methods: one for in16 and one for Object. // Casting an int32 into an int16 is not safe, so the Object overload // must be used instead.
источник
int
s с вызовом ==? Подсказка: нетoperator ==
метода дляInt32
, но есть дляString
.==
это не просто волшебство, а просто вызов метода (большинство программистов, вероятно, никогда не реализовали / не переопределили какой-либо оператор). Возможно, я мог бы добавить комментарий к вашему вопросу вместо того, чтобы добавлять свой ответ. Не стесняйтесь обновлять свою, если считаете, что то, что я сказал, актуально.==
для примитивных типов это не перегруженный оператор, а встроенная функция языка, которая компилируется вceq
инструкцию IL.== В примитивном
Console.WriteLine(age == newAge); // true
В примитивном сравнении оператор == ведет себя совершенно очевидно. В C # доступно множество перегрузок оператора ==.
Итак, в этом случае неявное преобразование из
int
кshort
аshort
кint
возможно. Таким образом, newAge преобразуется в int, и происходит сравнение, которое возвращает true, поскольку оба имеют одинаковое значение. Так что это эквивалентно:Console.WriteLine(age == (int)newAge); // true
.Equals () в примитиве
Console.WriteLine(newAge.Equals(age)); //false
Здесь нам нужно увидеть, что такое метод Equals (), мы вызываем Equals с переменной типа short. Итак, есть три возможности:
Первый тип здесь не используется, так как количество аргументов отличается, мы вызываем только один аргумент типа int. Третье также исключено, поскольку неявное преобразование int в short невозможно. Так здесь второй тип
Equals(object)
называется. Вshort.Equals(object)
:bool Equals(object z) { return z is short && (short)z == this; }
Итак, вот условие было проверено
z is short
которое является ложным, поскольку z является int, поэтому оно возвращает false.Вот подробная статья Эрика Липперта.
источник