我对引用类型中的内容相等性有点困惑。在任何一种情况下,我都不会压倒平等 - 所以为什么行为会有所不同。
参见2个简单的代码示例:
示例1:返回True
class Program
{
static void Main(string[] args)
{
object o1 = "ABC";
object o2 = "ABC";
Console.WriteLine("object1 and object2: {0}", o1.Equals(o2));
}
}
示例2:两个语句都返回False
class Program
{
static void Main(string[] args)
{
Person person1 = new Person("John");
Person person2 = new Person("John");
Console.WriteLine("person1 and person2: {0}", person1.Equals(person2));
Console.WriteLine("person1 and person2: {0}", ((object)person1).Equals((object)person2));
Console.ReadLine();
}
}
public class Person
{
private string personName;
public Person(string name)
{
this.personName = name;
}
}
答案 0 :(得分:8)
这里有两种效果:
字符串实习意味着实际即使您执行引用相等性检查,您仍会看到True
。你可以这样解决:
object o1 = new StringBuilder("ABC").ToString();
object o2 = new StringBuilder("ABC").ToString();
System.String
overrides the Equals
method来比较字符串的内容:
此方法执行序数(区分大小写和区分大小写)比较。
你可以在这里看到不同之处:
object o1 = new StringBuilder("ABC").ToString();
object o2 = new StringBuilder("ABC").ToString();
Console.WriteLine(o1.Equals(o2)); // Prints True due to overriding
Console.WriteLine(ReferenceEquals(o1, o2)); // Prints False
您的班级不会覆盖Equals
,因此您将获得default implementation in Object
,即比较参考资料:
如果当前实例是引用类型,则Equals(Object)方法测试引用相等性,并且对Equals(Object)方法的调用等同于对ReferenceEquals方法的调用。
您可以通过覆盖Equals
:
// It's easier to implement equality correctly on sealed classes
public sealed class Person
{
private readonly string personName;
public Person(string name)
{
if (name == null)
{
throw new ArgumentNullException("name");
}
this.personName = name;
}
public override bool Equals(object other)
{
Person person = other as Person;
return person != null && person.personName.Equals(personName);
}
// Must override GetHashCode at the same time...
public override int GetHashCode()
{
// Just delegate to the name here - it's the only thing we're
// using in the equality check
return personName.GetHashCode();
}
}
请注意,在我们可以使用的Equals
实现中:
return person != null && person.personName == personName;
...因为string
也重载了==
运算符。但那是另一回事:)
答案 1 :(得分:3)
示例1返回true
,因为Equals
正在比较这些值,因为该对象被视为字符串;而示例2是比较对象的实例,因为它们各自指向不同的内存块,它们不相等。
答案 2 :(得分:2)
默认情况下,参考类型的引用Equals
默认为ReferenceEquals
。您必须使用Person
的实例,因此它会返回false
。
String
会覆盖Equals
以实现值语义。因此,如果使用string
将两个单独的Equals
实例与相同的值进行比较,则返回true。
感谢字符串实习,"ABC"
指向同一个实例。因此,即使ReferenceEquals
在第一个示例中也会返回true
。
编译时类型与Equals
无关,因为它是一个虚方法。所以你的演员object
没有效果。转换为对象只会影响==
和!=
,因为它们已经过载,而不会被覆盖。
答案 3 :(得分:1)
重写字符串上的equals运算符以逐字节比较字符串。在第二个示例中,您将比较实例,即内存地址,这两个实例对于Person()的两个实例是不同的
答案 4 :(得分:0)
在第一种情况下,String.Equals
会覆盖Object.Equals
,并检查实际的字符串值。未使用引用相等性。在第二种情况下,正在使用默认引用相等。
但是,如果您使用object.ReferenceEquals
,则由于string interning会导致相同的行为,这会导致前两个对象指向内存中的相同字符串(相同的引用),因为你正在使用字符串文字。
答案 5 :(得分:0)
String
已覆盖其Equals
方法,因此如果两个字符串在同一顺序中包含完全相同的字符,则它们为Equal
。你的Person
没有这样的覆盖,所以从对象继承,使用引用等于它是相等的仲裁者。
答案 6 :(得分:0)
由于.net中的字符串实习,字符串引用相等(你会对它进行谷歌搜索)