[英]How to properly override equality?
我仍然是超載運營商的新手。 在我遇到這個問題之前,我以為自己做得很好。 在!=運算符上拋出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();
}
其他比較運算符留作練習。
它看起來像您要比較的Task
對象之一!=
設置為null
。 內置運算符!=
比較引用並且不會中斷,但運算符會嘗試取消引用任務,並中斷。
public static bool operator !=(Task t1, Task t2) {
if (ReferenceEquals(t1, null)) {
return !ReferenceEquals(t2, null); // return true only if t2 is *not* null
}
if (ReferenceEquals(t2, null)) {
return true; // we know that t1 is not null
}
return (t1.dateDue != t2.dateDue);
}
當兩個任務都為null
時,此實現返回false
。 您應該在==
運算符中實現對稱空值檢查。
public static bool operator !=(Task t1, Task t2)
{
if (null == t1 || null == t2) { return false;}
return (t1.dateDue != t2.dateDue);
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.