是否需要重载==运算符?

时间:2014-02-22 16:03:06

标签: c# operator-overloading equals

我认为在==下面的代码中的重载是不必要的,因为==已经比较了引用,如果没有重载。请告诉我方式。它应该使用单个参数Equals和单独包含的null比较来完成吗?

public class Student
{
    public string Name { get; set; }
    public int Age { get; set; }

    public override bool Equals(object param)
    {
    // If the cast is invalid, the result will be null
    Student student = param as Student;

    // Check if we have valid not null Student object
    if (student == null)
    {
        return false;
    }

    // Compare the reference type member fields
    if (!Object.Equals(this.Name, student.Name))
    {
        return false;
    }

    // Compare the value type member fields
    if (this.Age != student.Age)
    {
        return false;
    }
    return true;
    }

    public static bool operator ==(Student student1, Student student2)
    {
        return Student.Equals(student1, student2);
    }

    public static bool operator !=(Student student1, Student student2)
    {
        return !(Student.Equals(student1, student2));
    }

  ...

  }

2 个答案:

答案 0 :(得分:3)

  

我认为在==下面的代码中的重载是不必要的,因为==已经比较了引用,如果没有重载。

是的,但重点是因为运算符已经过载,您可以比较值的相等而不是引用标识。例如:

Student x = new Student { Name = "Jon", Age = 37 };
Student y = new Student { Name = "Jon", Age = 37 };

Console.WriteLine(x == y); // Prints True

如果没有运算符重载,上面的代码会打印False,因为xy的值引用了不同的对象。

这有时比显式调用Equals方法更方便。

因此,虽然在此处重载==并非严格必要(因为可以通过其他方式实现相同的结果),但 会影响行为。通过任何方式为所有类型重载==并不是一个好主意,但它可以使某些类型的事情变得简单得多。例如,我很高兴string重载==。关于何时重载==的好主意的讨论超出了这个答案的范围,幸运的是 - 对于初学者来说,这是一个有争议的问题。我对类很少这样做,但几乎总是对于值类型。 (编写自定义值类型非常罕见。)常规灰色区域是不可变引用类型...

请注意,当操作数是正确的编译时类型时,重载仅 。例如:

Student x = new Student { Name = "Jon", Age = 37 };
object y = new Student { Name = "Jon", Age = 37 };

Console.WriteLine(x == y); // Prints False

此处使用了 ,因为y的编译时类型为object,而不是Student

另一方面,这是一个可变类,它覆盖Equals,因此可能是GetHashCode,这是一个值得关注的问题。在实例可以以影响相等性的方式改变的类中覆盖Equals通常是个坏主意。它不适用于使用相等和散列的集合。例如:

var dictionary = new Dictionary<Student, string>();
var student = new Student { Name = "Jon", Age = 37 };
dictionary[student] = "foo";
Console.WriteLine(dictionary.ContainsKey(student)); // True
dictionary.Name = "Bob";
Console.WriteLine(dictionary.ContainsKey(student)); // False
Console.WriteLine(dictionary.Keys.First() == student); // True!

因为名称已更改,哈希代码已更改(我假设使用名称和年龄的相当简单的哈希代码实现)。这意味着正常的哈希检查将失败,即使引用仍在字典中。

如果你没有在之后将键添加到字典中,那么可以改变,但是它会使这些类型更容易出错,可以这么说。

答案 1 :(得分:1)

不必要且适得其反。在C#中,应用于类类型对象的==用于检查标识,而不是值相等。将==重载为equals是令人困惑和非惯用的,并且可能会导致某些容器类型出现问题。