C# · 12月 25, 2021

c# – 如何正确覆盖相等?

我仍然是超载操作符的新手.在我遇到这个问题之前,我以为自己做得很好.在!=运算符上抛出NullReferenceException.我假设它在CompareTo方法中使用它,但我不完全确定.如果有人能指出我正确的方向,我将非常感激. using System;using System.Collections.Generic;using System.ComponentModel;using System.Data;using System.Drawing;using System.Linq;using System.Text;using System.Windows.Forms;namespace WindowsFormsApplication2{ public partial class Form1 : Form { public Form1() { InitializeComponent(); List<Task> tasks = new List<Task>(); tasks.Add(new Task( “first”,DateTime.Now.AddHours(2))); tasks.Add(new Task( “second”,DateTime.Now.AddHours(4))); tasks.TrimExcess(); tasks.sort(); } } public class Task : IComparable { public Task() { } public Task(string nameIn,DateTime dueIn) { nameOfTask = nameIn; dateDue = dueIn; } DateTime dateDue; string nameOfTask; public static bool operator <(Task t1,Task t2) { return (t1.dateDue < t2.dateDue); } public static bool operator >(Task t1,Task t2) { return (t1.dateDue > t2.dateDue); } public static bool operator ==(Task t1,Task t2) { return (t1.dateDue == t2.dateDue); } public static bool operator !=(Task t1,Task t2) { return (t1.dateDue != t2.dateDue); } public override int GetHashCode() { return Int32.Parse(this.dateDue.ToString(“yyyymmddhhmmss”)); } public override bool Equals(System.Object obj) { if (obj == null) return false; Task t = obj as Task; if ((System.Object)t == null) return false; return (this.dateDue == t.dateDue); } int IComparable.CompareTo(object obj) { if (obj == null) return 1; Task t = obj as Task; if (t != null) { return this.dateDue.CompareTo(t.dateDue); } else throw new ArgumentException(“Object is not a Task”); } }}

当我注释掉binaory操作符时,程序按预期运行.我的问题是如何保护我的二元运算符免受空引用的影响,以便我可以将它们保存为手动比较?
感谢您的时间.

解决方法 到目前为止给出的答案都是错误的.接受的答案是错误的,因为它不小心递归.另一个答案是错误的,因为它表示null不等于null.

你的运算符实现都是错的;他们需要正确处理空输入.

你的GetHashCode实现已经彻底破坏了;您尝试将十四位数字放入可接受九位数的格式中.只需在日期调用GetHashCode;没有必要经历这种将它变成一个字符串然后把它变成一个数字的极限!

编写代码的正确方法是使用object.ReferenceEquals进行引用比较,而不是使用==和!=运算符;进行意外递归太容易了.

典型的模式是这样的:

public static bool operator ==(Task t1,Task t2) { if (object.ReferenceEquals(t1,t2)) return true; // All right. We kNow that they are (1) not the same object,and // (2) not both null. Maybe one of them is null. if (object.ReferenceEquals(t1,null)) return false; if (object.ReferenceEquals(t2,null)) return false; // They are not the same object and both are not null. return t1.dateDue == t2.dateDue;}public static bool operator !=(Task t1,Task t2) { // Simply call the == operator and invert it. return !(t1 == t2);}public override bool Equals(object t){ return (t as Task) == this; }public override int GetHashCode(){ return this.dateDue.GetHashCode();}

其他比较运算符留作练习.