4

ソート済みリストを実装しようとしています。リストに保存したいクラスを作成しましたが、何らかの理由で並べ替えメソッドを実行しようとすると、例外がスローされます。舞台裏で何かが私が実装nullしたメソッドへの参照を渡しているようです。CompareTo

これが、関連するコードであると私が信じているものです。

データ オブジェクトは次のように定義されます。

namespace PrioritisedRequestQueue
{
public class XactTask : IComparable<XactTask>
{
    public int priority;
    public DateTime submitted;
    public string name;

    public XactTask( int priority, DateTime submitted, string name)
    {
        this.priority = priority;
        this.submitted = submitted;
        this.name = name;
    }

    public int CompareTo(XactTask rhs )
    {
        //EXCEPTION OCCURS HERE AFTER A NULL RHS HAS BEEN PASSED IN**
        Console.WriteLine("comparing " + rhs.priority+"to "+this.priority); 

        if (rhs.priority <= this.priority)
        {
            Console.WriteLine("Entered first if");
            Console.WriteLine("comparing " + rhs.submitted + "to " + 
                this.submitted);
            if (rhs.submitted <= this.submitted)
            {
                Console.WriteLine("Entered second if");
                return 1;
            }
            else
            {
                return -1;
            }
        }
        else
        {
            Console.WriteLine("In else");
            return -1;
        }
    }
}
}

リストを保持するクラスは次のように定義されます。

namespace PrioritisedRequestQueue
{
    public class Class1
    {
        public List<XactTask> tasks;

        public Class1()
        {
            tasks = new List<XactTask>();
        }

        public void sort()
        {
            tasks.Sort();
        }

        public void add(XactTask task)
        {
            tasks.Add(task);

        }

    }
}

テストを行うために使用するプログラムは次のとおりです。

PrioritisedRequestQueue.Class1 tester = new PrioritisedRequestQueue.Class1();

tester.add(new PrioritisedRequestQueue.XactTask(1, DateTime.Now, "test1"));
tester.add(new PrioritisedRequestQueue.XactTask(1, DateTime.Now, "test2"));
Console.WriteLine(tester.tasks[0].name);
Console.WriteLine(tester.tasks[1].name);
tester.tasks.Sort();

テスト プログラムの出力は次のとおりです。

 comparing 1to 1 Entered first if
 comparing 16/05/2011 14:41:57to 16/05/2011 14:41:57 
 Entered second if
 comparing 1to 1 Entered first if
 comparing 16/05/2011 14:41:57to 16/05/2011 14:41:57 
 Entered second if
 comparing 1to 1 
 Entered first if
 comparing 16/05/2011 14:41:57to 16/05/2011 14:41:57 
 Entered second if
 comparing 1to 1 
 Entered first if
 comparing 16/05/2011 14:41:57to 16/05/2011 14:41:57 
 Entered second if

null次に、 rhs オブジェクトを比較メソッドに渡すように見え、 rhsNullReferenceExceptionの優先度にアクセスしようとすると が返されます。

なぜこれが起こっているのか、これに対処するために何をしなければならないのか教えていただけますか?

さらに情報が必要な場合はお知らせください。

4

1 に答える 1

9

コードを実行すると、正しく実装されていないInvalidOperationExceptionため、エラーが発生します。CompareTo

が同じ場合(つまり、このオブジェクトと比較対象のオブジェクトが等しい場合)は、CompareTo実装によって返される必要があります。の場合も失敗するべきではありませんが、一貫した方法で順序付けする必要があります。これは通常、常にすべての有効なオブジェクトの前にソートに戻ることによって行われます。0rhsthisrhs == nullnull1null

IComparable.CompareToのドキュメントには、Sort が正しく機能するために従わなければならない次の規則がリストされています。

  • A.CompareTo(A)ゼロを返す必要があります。

  • A.CompareTo(B)ゼロを返す 場合は、ゼロB.CompareTo(A)を返す必要があります。

  • A.CompareTo(B)ゼロを返し、ゼロを B.CompareTo(C)返す場合、 ゼロを返すA.CompareTo(C)必要があります。

  • A.CompareTo(B)0 以外の値を返す場合B.CompareTo(A) は、反対の符号の値を返す必要があります。

  • A.CompareTo(B)ゼロに等しくない値 x を返し、x と 同じB.CompareTo(C)符号の値 y を返す A.CompareTo(C)場合、x および y と同じ符号の値を返す必要があります。

この問題を解決するには、 の実装が のCompareTo場合に 0 を返すようにしますpriority == rhs.priority && submitted == rhs.submitted

于 2011-05-16T14:14:11.643 に答える