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

二項演算子をコメントアウトすると、プログラムは意図したとおりに機能します。私の質問は、二項演算子を null 参照から保護して、手動で比較できるようにするにはどうすればよいですか? お時間をいただきありがとうございます。

4

3 に答える 3

14

これまでに与えられた答えは両方とも間違っています。誤って再帰するため、受け入れられた答えは間違っています。もう 1 つの答えは、null は null と等しくないため、間違っています。

演算子の実装はすべて間違っています。null 入力を正しく処理するために必要です。

GetHashCode の実装は深く壊れています。14 桁の数値を、9 桁を受け入れる形式に変換しようとしています。日付で GetHashCode を呼び出すだけです。それを文字列に変換してから数値に変換するというこのリガマロールを実行する必要はありません。

コードを記述する正しい方法は、 and演算子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();
}

他の比較演算子は演習として残します。

于 2012-04-23T22:20:45.083 に答える
3

Task比較しているオブジェクトの1つがに!=設定されているよう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 に答える