我在silverlight应用程序中有一个比较2个字符串的条件,由于某种原因,当我使用==时,它返回false而. equals()返回true。
代码如下:
if (((ListBoxItem)lstBaseMenu.SelectedItem).Content.Equals("Energy Attack"))
{
// Execute code
}
if (((ListBoxItem)lstBaseMenu.SelectedItem).Content == "Energy Attack")
{
// Execute code
}
你知道为什么会这样吗?
当比较对象引用和字符串时(即使对象引用引用了字符串),特定于字符串类的==操作符的特殊行为将被忽略。
Normally (when not dealing with strings, that is), Equals compares values, while == compares object references.
If two objects you are comparing are referring to the same exact instance of an object, then both will return true, but if one has the same content and came from a different source (is a separate instance with the same data), only Equals will return true. However, as noted in the comments, string is a special case because it overrides the == operator so that when dealing purely with string references (and not object references), only the values are compared even if they are separate instances. The following code illustrates the subtle differences in behaviors:
string s1 = "test";
string s2 = "test";
string s3 = "test1".Substring(0, 4);
object s4 = s3; // Notice: set to object variable!
Console.WriteLine($"{object.ReferenceEquals(s1, s2)} {s1 == s2} {s1.Equals(s2)}");
Console.WriteLine($"{object.ReferenceEquals(s1, s3)} {s1 == s3} {s1.Equals(s3)}");
Console.WriteLine($"{object.ReferenceEquals(s1, s4)} {s1 == s4} {s1.Equals(s4)}");
输出结果为:
True True True // s1, s2
False True True // s1, s3
False False True // s1, s4
简介:
Variables |
.ReferenceEquals |
== |
.Equals |
s1, s2 |
True |
True |
True |
s1, s3 |
False |
True |
True |
s1, s4 |
False |
False |
True |
这是由于值相等(equal方法)和引用相等(==运算符),因为equal方法检查值,而相同的==检查引用。
==运算符覆盖https://referencesource.microsoft.com/上string类内可用的代码
现在更容易理解了,equal方法也有两个实现一个来自string类本身,一个来自object类。它对性能的影响以及我也运行一些基本的代码,并试图理解基准测试。
我分享下面的结果,如果我错了,请纠正或建议。有3种情况,我对所有情况运行了相同的代码,这就是结果。
情况1:这里我使用的是字符串。相等的方法比较两个字符串和两个字符串有相同的值。string.equals (a, b)
第一次运行:5608195 tick
第二次运行:5529387个刻度
第三次运行:5622569滴答
总蜱数:16760151
情况2:这里我使用的是字符串。Equal()方法(重载的一个)用于比较两个字符串,并且两个字符串具有相同的值。
a.equals (b)
第一次运行:6738583滴答
第二轮:6452927
第三轮:7168897个刻度
总蜱虫= 20360407
情况3:这里我使用==操作符比较2个字符串,两个字符串都有相同的值。
a = =
第一次运行:6652151滴答
第二次运行:7514300个tick
第三轮:7634606滴答
总蜱虫= 21801057
class Program
{
private static int count;
static string a = "abcdef";
static string b = "abcdef";
static void Main(string[] args)
{
for (int j = 1; j <= 3; j++)
{
Stopwatch sw = new Stopwatch();
sw.Start();
for (int i = 1; i <= 1000; i++)
{
checkString();
}
sw.Stop();
Console.WriteLine(sw.ElapsedTicks);
}
Console.ReadLine();
}
public static void checkString()
{
for (int i = 1; i <= 100000; i++)
{
if (a==b)
count++;
}
}
}
==和. equals都依赖于实际类型中定义的行为和调用位置上的实际类型。两者都只是方法/操作符,可以在任何类型上重写,并给定作者希望的任何行为。根据我的经验,我发现人们在对象上实现. equals却忽略了operator ==是很常见的。这意味着. equals将实际测量值是否相等,而==将测量它们是否是相同的引用。
当我处理一个定义不断变化的新类型或编写泛型算法时,我发现最佳实践如下
如果我想在c#中比较引用,我使用Object。直接使用ReferenceEquals(在泛型情况下不需要)
如果我想比较值,我使用EqualityComparer<T>。默认的
在某些情况下,当我觉得==的用法不明确时,我会显式地使用Object。在代码中引用等号以消除歧义。
Eric Lippert最近写了一篇博文,主题是为什么在CLR中有两种相等的方法。值得一读
http://blogs.msdn.com/ericlippert/archive/2009/04/09/double-your-dispatch-double-your-fun.aspx
Equals()和==是否相同取决于实现。因为c#允许用户分别为Equals()和==设置不同的行为。
class CompareTest
{
public readonly int val;
public CompareTest(int val)
{
this.val = val;
}
public override bool Equals(object obj)
{
return obj is CompareTest test && this.val == test.val;
}
public override int GetHashCode()
{
return val;
}
public static bool operator == (CompareTest a, object b)
{
return Equals(a, b);
}
public static bool operator != (CompareTest a, object b)
{
return !(a == b);
}
}
在本例中,我使Equals()和==具有相同的行为。但如果我让他们不一样呢?例如:
public static bool operator == (CompareTest a, object b)
{
return false;
}
Equals()正常工作,但==永远不会工作。
此外,虽然我让它们具有相同的行为,但仍然有一个区别:哪个==函数将被调用取决于左边的值:
Compare Test a = new CompareTest(1);
object b = new CompareTest(1);
CompareTest c = new CompareTest(1);
Debug.Log("AB " + (a == b)); // true
Debug.Log("BA " + (b == a)); // false! because it calls object's == function
Debug.Log("AC " + (a == c)); // true
Debug.Log("CA " + (c == a)); // true