参考类型的平等

Pat*_*ick 7 c#

我特别关注引用类型中的内容相等性.在任何一种情况下,我都不会压倒平等 - 所以为什么行为会有所不同.

参见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));
    }
}
Run Code Online (Sandbox Code Playgroud)

示例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;
    }
}
Run Code Online (Sandbox Code Playgroud)

Jon*_*eet 8

这里有两种效果:

  • 字符串实习这意味着实际上即使执行参考平等检查,你仍然会看到True.你可以像这样修复:

    object o1 = new StringBuilder("ABC").ToString();
    object o2 = new StringBuilder("ABC").ToString();
    
    Run Code Online (Sandbox Code Playgroud)
  • System.String 覆盖Equals方法,比较内容的字符串:

    此方法执行序数(区分大小写和文化不敏感)比较.

    你可以在这里看到差异:

    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
    
    Run Code Online (Sandbox Code Playgroud)

您的类不会覆盖Equals,因此您将获得默认实现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();
    }
}
Run Code Online (Sandbox Code Playgroud)

请注意,在Equals我们可以使用的实现中:

return person != null && person.personName == personName;
Run Code Online (Sandbox Code Playgroud)

...因为操作员string 超载了==.但那是另一回事:)