我在Silverlight应用程序中有一个比较2个字符串的条件,由于某些原因,当我使用 ==
时它返回 false 而 .Equals()
返回 true .
这是代码:
if (((ListBoxItem)lstBaseMenu.SelectedItem).Content.Equals("Energy Attack"))
{
// Execute code
}
if (((ListBoxItem)lstBaseMenu.SelectedItem).Content == "Energy Attack")
{
// Execute code
}
任何理由为什么会这样?
16 回答
当
==
用于object
类型的表达式时,它将解析为System.Object.ReferenceEquals .Equals只是一个
virtual
方法并且表现如此,因此将使用被覆盖的版本(对于string
类型比较内容) .将对象引用与字符串进行比较时(即使对象引用引用字符串),将忽略特定于字符串类的
==
运算符的特殊行为 .通常(当不处理字符串时),
Equals
比较 values ,而==
比较 object references . 如果您要比较的两个对象是指对象的同一个确切实例,则两者都将返回true,但如果一个具有相同的内容并来自不同的源(是具有相同数据的单独实例),则只有Equals将返回true . 但是,如注释中所述,字符串是一种特殊情况,因为它会覆盖==
运算符,因此在纯粹使用字符串引用(而不是对象引用)进行处理时,即使它们是单独的实例,也只会比较这些值 . 以下代码说明了行为的细微差别:输出是:
==
和.Equals
都取决于实际类型中定义的行为和呼叫站点的实际类型 . 两者都只是方法/运算符,可以在任何类型上重写,并给出作者所希望的任何行为 . 根据我的经验,我发现人们在一个对象上实现.Equals
但忽略了实现operator==
是很常见的 . 这意味着.Equals
将实际测量值的相等性,而==
将测量它们是否是相同的参考 .当我使用一种新的类型,其定义是不变的或编写通用算法时,我发现最佳实践如下
如果我想比较C#中的引用,我直接使用
Object.ReferenceEquals
(在通用情况下不需要)如果我想比较值我使用
EqualityComparer<T>.Default
在某些情况下,当我觉得
==
的用法不明确时,我会在代码中明确使用Object.Reference
equals来消除歧义 .Eric Lippert最近做了一篇关于为什么CLR中有两种平等方法的博客文章 . 值得一读
首先,存在差异 . 对于数字
对于字符串
在这两种情况下,
==
的行为都比.Equals
更有用我想补充一点,如果你将对象转换为字符串,那么它将正常工作 . 这就是为什么编译器会给你一个警告说:
== Operator 1.如果操作数为Value Types且它们的值相等,则返回true,否则返回false . 2.如果操作数是Reference Types,但字符串除外并且两者都引用同一个对象,则返回true,否则返回false . 3.如果操作数是字符串类型且它们的值相等,则返回true,否则返回false .
.Equals 1.如果操作数是引用类型,则执行Reference Equality,如果两者都引用同一对象,则返回true,否则返回false . 2.如果操作数是值类型,那么与==运算符不同,它首先检查它们的类型,如果它们的类型相同则执行==运算符,否则返回false .
据我所知,答案很简单:
==比较对象引用 .
.Equals比较对象内容 .
String数据类型总是像内容比较一样 .
我希望我是对的,它回答了你的问题 .
因为到目前为止还没有提到
.Equal
方法的静态版本,所以我想在此处添加它来总结并比较3种变体 .其中
MyString
是来自代码中其他位置的变量 .Background info and to summerize:
在Java中使用
==
比较字符串不应该使用 . 我提到这个,以防你需要使用这两种语言,并告诉你使用==
也可以用C#中更好的东西替换 .在C#中,只要使用方法1或方法2比较字符串就没有实际区别两者都是字符串类型 . 但是,如果一个是null,一个是另一个类型(如整数),或者一个代表具有不同引用的对象,那么,正如初始问题所示,您可能会遇到比较内容的相等性可能不会返回什么你期待 .
Suggested solution:
因为在比较事物时使用
==
与使用.Equals
完全相同,所以可以使用静态String.Equals方法 . 这样,如果双方不是同一类型,您仍然会比较内容,如果一个为null,您将避免该异常 .写一点,但在我看来,使用更安全 .
以下是从Microsoft复制的一些信息:
参数
a
字符串要比较的第一个字符串,或
null
.b
字符串要比较的第二个字符串,或
null
.返回
Boolean
true
如果a
的值与b
的值相同;否则,false
. 如果a
和b
都是null
,则该方法返回true
.我在这里有点困惑 . 如果Content的运行时类型是string类型,则==和Equals都应返回true . 但是,由于情况似乎并非如此,因此Content的运行时类型不是字符串,并且调用Equals就可以执行引用相等,这就解释了Equals(“Energy Attack”)失败的原因 . 但是,在第二种情况下,应该在编译时决定调用哪个重载==静态运算符,并且此决定似乎是==(字符串,字符串) . 这告诉我内容提供了对字符串的隐式转换 .
@BlueMonkMN的早期答案还有另一个方面 . 另外一个方面是@ Drahcir Headers 问题的答案也取决于我们如何得出
string
值 . 为了显示:输出是:
再补充一点 .
.EqualsTo()
方法为您提供了与文化和区分大小写进行比较的规定 .C#中的
==
标记用于两个不同的相等检查运算符 . 当编译器遇到该标记时,它将检查被比较的类型中的任何一个是否为要比较的特定组合类型(*)或者两种类型都可以转换的类型组合实现了相等运算符重载 . 如果编译器发现这样的重载,它将使用它 . 否则,如果这两种类型都是引用类型,并且它们不是不相关的类(可以是接口,也可以是相关类),编译器会将==
视为引用比较运算符 . 如果两个条件都不适用,则编译将失败 .请注意,其他一些语言对两个相等检查运算符使用单独的标记 . 例如,在VB.NET中,
=
标记仅在表达式中用于可重载的相等检查运算符,而Is
用作引用测试或空值测试运算符 . 在不覆盖相等检查运算符的类型上使用=
将失败,因为尝试将Is
用于除测试引用相等或无效之外的任何其他目的 .(*)类型通常只有重载等于与自身进行比较,但是类型可以用于重载等于运算符以与其他特定类型进行比较;例如,
int
可以(和恕我直言应该但没有)定义一个相等的运算符,以便与float
进行比较,这样16777217就不会报告自己等于16777216f . 实际上,由于没有定义这样的运算符,C#会将int
提升为float
,在等号检查运算符看到之前将其四舍五入为16777216f;然后,该运算符会看到两个相等的浮点数并将它们报告为相等,而不知道发生的舍入 .真的很棒的答案和例子!
我想补充两者之间的根本区别,
考虑到这个概念,如果你计算出任何一个例子(通过查看左手和右手引用类型,并检查/知道类型实际上是否有==运算符重载和等于被覆盖),你肯定会得到正确的答案 .
当我们创建任何对象时,对象有两个部分,一个是内容,另一个是对该内容的引用 .
==
比较两者内容和参考;equals()
仅比较内容http://www.codeproject.com/Articles/584128/What-is-the-difference-between-equalsequals-and-Eq
==
==运算符可用于比较任何类型的两个变量,并且 it simply compares the bits .
注意:int的左侧有更多的零,但我们在这里并不关心 .
int a(00000011)== byte b(00000011)
记住==运算符只关心变量中位的模式 .
使用==如果两个引用(基元)引用堆上的同一个对象 .
无论变量是引用还是基元,规则都是相同的 .
a == c为真a == b为假
a和c的位模式相同,所以使用==它们是相同的 .
Equal():
使用equals()方法查看 if two different objects are equal .
比如两个不同的String对象,它们都代表“Jane”中的字符
Equal和==之间的唯一区别在于对象类型比较 . 在其他情况下,例如引用类型和值类型,它们几乎相同(要么两者都是逐位相等,要么两者都是引用相等) .
object:Equals:bit-wise equality ==:引用相等
string :(等于和==对于字符串是相同的,但如果其中一个字符串更改为object,则比较结果将不同)Equals:bit-wise equality ==:bit-wise equality
有关更多说明,请参阅here .