题
我在 silverlight 应用程序中有一个比较 2 个字符串的条件,由于某种原因,当我使用 ==
它返回 错误的 尽管 .Equals()
回报 真的.
这是代码:
if (((ListBoxItem)lstBaseMenu.SelectedItem).Content.Equals("Energy Attack"))
{
// Execute code
}
if (((ListBoxItem)lstBaseMenu.SelectedItem).Content == "Energy Attack")
{
// Execute code
}
有什么原因导致这种情况发生吗?
解决方案
当 ==
用于 object
类型的表达式时,它将解析为 System.Object.ReferenceEquals
。
Equals
只是一个<代码>虚拟方法并且表现如此,因此将使用被覆盖的版本(对于 string
类型比较内容)。
其他提示
将对象引用与字符串进行比较时(即使对象引用引用字符串),将忽略特定于字符串类的 ==
运算符的特殊行为。
通常(当不处理字符串时), Equals
比较值,而 ==
比较对象引用即可。
如果您要比较的两个对象是指对象的同一个确切实例,则两者都将返回true,但如果一个具有相同的内容并来自不同的源(是具有相同数据的单独实例),则只有Equals将返回true。但是,如注释中所述,字符串是一种特殊情况,因为它覆盖了 ==
运算符,因此当纯粹使用字符串引用(而不是对象引用)进行处理时,只有值才会进行比较,即使它们是是单独的实例。以下代码说明了行为的细微差别:
string s1 = "test";
string s2 = "test";
string s3 = "test1".Substring(0, 4);
object s4 = s3;
Console.WriteLine("{0} {1} {2}", object.ReferenceEquals(s1, s2), s1 == s2, s1.Equals(s2));
Console.WriteLine("{0} {1} {2}", object.ReferenceEquals(s1, s3), s1 == s3, s1.Equals(s3));
Console.WriteLine("{0} {1} {2}", object.ReferenceEquals(s1, s4), s1 == s4, s1.Equals(s4));
输出结果为:
True True True
False True True
False False True
==
和 .Equals
两者都依赖于实际类型中定义的行为和调用站点的实际类型。两者都只是方法/运算符,可以在任何类型上重写,并给出作者希望的任何行为。根据我的经验,我发现人们普遍实施 .Equals
在一个对象上但忽略实现运算符 ==
. 。这意味着 .Equals
实际上会衡量值的相等性,而 ==
将测量它们是否是相同的参考。
当我使用定义不断变化的新类型或编写通用算法时,我发现最佳实践如下
- 如果我想比较 C# 中的引用,我使用
Object.ReferenceEquals
直接(一般情况下不需要) - 如果我想比较我使用的值
EqualityComparer<T>.Default
在某些情况下,当我觉得使用 ==
是不明确的我会明确使用 Object.Reference
在代码中使用 equals 来消除歧义。
Eric Lippert 最近发表了一篇博客文章,主题是为什么 CLR 中有两种相等的方法。值得一读
首先,是的区别。对于数字
> 2 == 2.0
True
> 2.Equals(2.0)
False
对于字符串
> string x = null;
> x == null
True
> x.Equals(null)
NullReferenceException
在这两种情况下, ==
的行为都比 .Equals
我想补充一点,如果你将对象转换为字符串,那么它将正常工作。这就是为什么编译器会给你一个警告:
可能的意外参考比较;得到一个价值比较, 施放左侧以输入'string'
据我所知,答案很简单:
- ==比较对象引用。
- .Equals比较对象内容。
- 字符串数据类型总是像内容比较一样。 醇>
我希望我是对的,并且它回答了你的问题。
因为到目前为止还没有提到 .Equal
方法的静态版本,所以我想在此处添加它来总结并比较3种变体。
MyString.Equals("Somestring")) //Method 1
MyString == "Somestring" //Method 2
String.Equals("Somestring", MyString); //Method 3 (static String.Equals method) - better
其中 MyString
是来自代码中其他位置的变量。
背景信息并总结:
在Java中使用 ==
来比较字符串不应该使用。我提到这个,以防你需要使用这两种语言
让你知道使用 ==
也可以用C#中更好的东西替换。
在C#中,使用方法1或方法2比较字符串没有实际区别,只要两者都是字符串类型。但是,如果一个为null,一个是另一个类型(如整数),或者一个代表具有不同引用的对象,那么,如初始问题所示,您可能会遇到比较内容的相等性可能不会返回什么你期待。
建议的解决方案:
因为在比较事物时使用 ==
与使用 .Equals
不完全相同,所以可以使用 static String.Equals 方法代替。这样,如果双方不是同一类型,你仍然会比较内容,如果一个为null,你将避免异常。
bool areEqual = String.Equals("Somestring", MyString);
写一点,但在我看来,使用更安全。
以下是从Microsoft复制的一些信息:
public static bool Equals (string a, string b);
参数
a
String
要比较的第一个字符串,或 null
。
b
String
要比较的第二个字符串,或 null
。
返回 Boolean
a
的值与 b
的值相同,则 true
;否则, false
。如果 a
和 b
都是 null
,则该方法返回 true
。
我在这里有点困惑。如果Content的运行时类型是string类型,则==和Equals都应返回true。但是,由于情况似乎并非如此,因此内容的运行时类型不是字符串,并且调用其上的Equals正在执行引用相等,这解释了为什么Equals(“Energy Attack”)失败。但是,在第二种情况下,应该在编译时决定调用哪个重载==静态运算符,并且此决定似乎是==(字符串,字符串)。这告诉我内容提供了对字符串的隐式转换。
@BlueMonkMN的早期答案还有另一个方面。另外一个方面是@ Drahcir标题问题的答案也取决于我们如何到达 string
值。举例说明:
string s1 = "test";
string s2 = "test";
string s3 = "test1".Substring(0, 4);
object s4 = s3;
string s5 = "te" + "st";
object s6 = s5;
Console.WriteLine("{0} {1} {2}", object.ReferenceEquals(s1, s2), s1 == s2, s1.Equals(s2));
Console.WriteLine("\n Case1 - A method changes the value:");
Console.WriteLine("{0} {1} {2}", object.ReferenceEquals(s1, s3), s1 == s3, s1.Equals(s3));
Console.WriteLine("{0} {1} {2}", object.ReferenceEquals(s1, s4), s1 == s4, s1.Equals(s4));
Console.WriteLine("\n Case2 - Having only literals allows to arrive at a literal:");
Console.WriteLine("{0} {1} {2}", object.ReferenceEquals(s1, s5), s1 == s5, s1.Equals(s5));
Console.WriteLine("{0} {1} {2}", object.ReferenceEquals(s1, s6), s1 == s6, s1.Equals(s6));
输出结果为:
True True True
Case1 - A method changes the value:
False True True
False False True
Case2 - Having only literals allows to arrive at a literal:
True True True
True True True
再添加一个答案。
.EqualsTo()
方法为您提供了与文化和区分大小写进行比较的条款。
C#中的 ==
标记用于两个不同的相等检查运算符。当编译器遇到该标记时,它将检查被比较的类型中的任何一个是否为要比较的特定组合类型(*)或者两种类型都可以转换的类型组合实现了相等运算符重载。如果编译器发现这样的重载,它将使用它。否则,如果这两种类型都是引用类型并且它们不是不相关的类(可以是接口,也可以是相关类),编译器会将 ==
视为引用比较运算符。如果两种情况都不适用,则编译将失败。
请注意,其他一些语言对两个相等检查运算符使用单独的标记。例如,在VB.NET中, =
标记仅在表达式中用于可重载的相等检查运算符, Is
用作引用测试或null-测试操作员。在不覆盖相等检查运算符的类型上使用 =
将失败,因为尝试使用 Is
用于测试引用相等或无效之外的任何其他目的。
(*)类型通常只有重载等于与自身进行比较,但是对于类型来说,重载等于运算符以与其他特定类型进行比较可能是有用的。例如, int
可以(和恕我直言应该但没有)定义一个相等的运算符,以便与 float
进行比较,这样16777217就不会报告自己等于16777216f。实际上,由于没有定义这样的运算符,C#会将 int
提升为 float
,在等号检查操作符看到之前将其四舍五入为16777216f;该运算符然后看到两个相等的浮点数并将它们报告为相等,不知道发生的舍入。
非常好的答案和例子!
我只想补充两者之间的根本区别,
==
等运算符不是多态的,而Equals
是
考虑到这个概念,如果你计算出任何一个例子(通过查看左手和右手引用类型,并检查/知道类型实际上是否有==运算符重载和等于被覆盖),你肯定会得到正确的答案。
当我们创建任何对象时,对象有两个部分,一个是内容,另一个是对该内容的引用。
==
比较内容和参考;
equals()
仅比较内容
http:// www。 codeproject.com/Articles/584128/What-is-the-difference-between-equalsequals-and-Eq
<强> == 强>
==运算符可用于比较任何类型的两个变量,它只是比较位。
int a = 3;
byte b = 3;
if (a == b) { // true }
注意:int的左侧有更多的零,但我们在这里并不关心。
int a(00000011)== byte b(00000011)
记住==运算符只关心变量中位的模式。
使用==如果两个引用(基元)引用堆上的同一个对象。
无论变量是引用还是原语,规则都是相同的。
Foo a = new Foo();
Foo b = new Foo();
Foo c = a;
if (a == b) { // false }
if (a == c) { // true }
if (b == c) { // false }
a == c是真的 a == b是假的
a和c的位模式相同,所以使用==。
它们是相同的<强> 等于(): 强>
使用equals()方法查看两个不同的对象是否相等。
例如两个不同的String对象,它们都代表“Jane”中的字符
Equal和==之间的唯一区别在于对象类型比较。在其他情况下,例如引用类型和值类型,它们几乎相同(要么两者都是逐位相等,要么两者都是引用相等)。
对象: 等于:逐位平等 ==:引用相等
string :(等于和==对于字符串是相同的,但如果其中一个字符串更改为object,则比较结果将不同) 等于:逐位平等 ==:逐位平等
有关详细说明,请参见此处。