对于C#中的原语,==和Equals()之间有什么区别?

Moh*_*ani 179 c# compare

考虑以下代码:

int age = 25;
short newAge = 25;
Console.WriteLine(age == newAge);  //true
Console.WriteLine(newAge.Equals(age)); //false
Console.ReadLine();
Run Code Online (Sandbox Code Playgroud)

这两个intshort是原始类型,但有一个比较==返回true,并用比较Equals返回false.

为什么?

SLa*_*aks 261

简短回答:

平等很复杂.

详细解答:

object.Equals(object)如果boxed object类型和值相同,则基元类型会覆盖基数并返回true .(请注意,它也适用于可空类型;非null可空类型总是用于基础类型的实例.)

由于newAge是a short,Equals(object)如果传递具有相同值的盒装短片,则其方法仅返回true .你正在传递一个盒子int,所以它返回false.

相反,==操作员被定义为服用两个ints(或shorts或longs).
当您使用a int和a 调用它时short,编译器将隐式转换为shortto int并按int值比较结果s.

其他使其工作的方法

原始类型也有自己的Equals()方法,可以接受相同的类型.
如果编写age.Equals(newAge),编译器将选择int.Equals(int)最佳重载并隐式转换shortint.然后它会返回true,因为这个方法只是int直接比较s.

short也有一个short.Equals(short)方法,但int不能隐式转换为short,所以你不是在调用它.

您可以强制它使用强制转换来调用此方法:

Console.WriteLine(newAge.Equals((short)age)); // true
Run Code Online (Sandbox Code Playgroud)

这将short.Equals(short)直接调用,无需拳击.如果age大于32767,则会抛出溢出异常.

您也可以调用short.Equals(object)重载,但显式传递一个盒装对象,以便它获得相同的类型:

Console.WriteLine(newAge.Equals((object)(short)age)); // true
Run Code Online (Sandbox Code Playgroud)

与前一个替代方案一样,如果它不适合,则会抛出溢出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;
    }
Run Code Online (Sandbox Code Playgroud)

进一步阅读:

Eric Lippert.

  • @SLaks,如果我们调用`long == int`,`int`隐式转换为`long`吧? (3认同)
  • @SLaks是,但你的答案"传递的值"的措辞可以双向解释(作为开发人员传递的值,或拆箱后CLR实际传递的值).我猜这个不知道答案的临时用户会把它读成前者 (2认同)
  • @Rachel:除非那不是真的; _default_` ==`运算符通过引用比较引用类型.对于值类型,以及重载`==`的类型,它不会. (2认同)

Sim*_*ead 55

因为没有超载short.Equals接受了int.因此,这被称为:

public override bool Equals(object obj)
{
    return obj is short && this == (short)obj;
}
Run Code Online (Sandbox Code Playgroud)

obj不是short......所以,这是假的.


wdo*_*jos 12

对于值类型,.Equals要求两个对象具有相同的类型并具有相同的值,而==只测试两个值是否相同.

Object.Equals
http://msdn.microsoft.com/en-us/library/bsc2ak47(v=vs.110).aspx


小智 12

当你传递intshort'等于你通过时object:

在此输入图像描述 所以这个伪代码运行:

return obj is short && this == (short)obj;
Run Code Online (Sandbox Code Playgroud)


use*_*959 10

==用于检查相等的条件,它可以被认为是一个运算符(布尔运算符),只是为了比较2个东西,这里数据类型无关紧要,因为会进行类型转换,Equals也用于检查等于条件,但在这种情况下,数据类型应该相同.N Equals是一种非操作者的方法.

以下是您提供的一个小例子,这将简要说明不同之处.

int x=1;
short y=1;
x==y;//true
y.Equals(x);//false
Run Code Online (Sandbox Code Playgroud)

在上面的例子中,X和Y具有相同的值,即1,当我们使用时==,它将返回true,如同情况一样==,编译器将short类型转换为int并给出结果.

当我们使用时Equals,比较完成,但类型转换不是由编译器完成的,因此返回false.

伙计们,如果我错了,请告诉我.


sup*_*cat 6

在方法或运算符参数不是所需类型的许多上下文中,C#编译器将尝试执行隐式类型转换.如果编译器可以通过添加隐式转换使所有参数满足其运算符和方法,那么即使在某些情况下(特别是使用相等测试!),结果可能会令人惊讶.

此外,每种值类型例如intshort实际上描述了一种值和一种对象(*).隐式转换的存在是为了将值转换为其他类型的值,并将任何类型的值转换为其对应的对象类型,但不同类型的对象不能隐式地相互转换.

如果使用==运算符来比较a short和a int,short则将隐式转换为a int.如果其数值是等于的int中,int以将其转换将等于int它被进行比较.但是,如果尝试Equals在short上使用该方法将其与a进行比较int,那么唯一能够满足Equals方法重载的隐式转换就是转换为对应的对象类型int.当short询问它是否与传入的对象匹配时,它将观察到所讨论的对象是一个int而不是一个short,从而得出它不可能相等的结论.

一般来说,虽然编译器不会抱怨它,但应该避免比较不同类型的东西; 如果人们对将事物转换为共同形式是否会产生相同结果感兴趣,则应明确执行此类转换.例如,考虑一下

int i = 16777217;
float f = 16777216.0f;

Console.WriteLine("{0}", i==f);
Run Code Online (Sandbox Code Playgroud)

有三种方法可以将a int与a 进行比较float.有人可能想知道:

  1. 匹配最接近的可能floatintfloat什么?
  2. float匹配的整数部分是int
  3. intfloat表示相同的数值.

如果一个人试图直接比较intfloat编译代码将回答第一个问题; 然而,程序员的意图是否远非显而易见.改变比较(float)i == f会清楚地表明第一个含义是有意的,或者(double)i == (double)f会导致代码回答第三个问题(并清楚地表明它是预期的).

(*)即使C#规范将类型的值System.Int32视为类型的对象System.Int32,这样的视图也与代码在平台上运行的要求相矛盾,该平台的规范将值和对象视为居住在不同的宇宙中.此外,如果T是引用类型,并且x是a T,那么类型的引用T应该能够引用x.因此,如果v类型的变量Int32包含a,则类型Object的引用Object应该能够保存v对其内容的引用.事实上,类型的引用Object将能够指向一个对象,该对象保存从其自身复制的数据v,但不能复制v到其内容.这表明它既不是v也不是它的内容Object.


Sug*_*kar 5

等于() 是一个方法System.Object的
语法:公共虚拟布尔equals()方法
的建议,如果我们要比较两个对象的状态,那么我们应该使用的equals()方法

如上所述答案==运算符比较值相同.

请不要与ReferenceEqual混淆

Reference Equals()
语法:public static bool ReferenceEquals()
它确定指定的对象实例是否属于同一个实例

  • 这根本不回答这个问题. (8认同)