7

我对重载运算符仍然很陌生。在遇到这个问题之前,我认为我做得很好。在 != 运算符上引发 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");
        }
    }
}

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

4

3 回答 3

14

到目前为止给出的两个答案都是错误的。接受的答案是错误的,因为它意外地递归。另一个答案是错误的,因为它说 null 不等于 null。

您对运算符的实现都是错误的;他们需要正确处理空输入。

您的 GetHashCode 实现被严重破坏;您试图将一个十四位数字转换成可以接受九位数字的格式。只需在日期调用 GetHashCode;没有必要把它变成一个字符串,然后把它变成一个数字!

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

典型的模式是这样的:

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();
}

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

于 2012-04-23T22:20:45.083 回答
3

看起来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);
}

false当两个任务都是 时,此实现返回null。您应该在运算符中实施对称空值检查==

于 2012-04-23T21:35:05.400 回答
-4
 public static bool operator !=(Task t1, Task t2) 
        { 
              if (null == t1 || null == t2) { return false;}
                return (t1.dateDue != t2.dateDue); 

        } 
于 2012-04-23T21:34:50.470 回答