سؤال

أحاول تنفيذ قائمة مرتبة.لقد قمت بإنشاء الفصل الذي أريد تخزينه في القائمة، ولكن لسبب ما عندما أحاول تشغيل طريقة الفرز، أحصل على استثناء.يبدو أن شيئا وراء الكواليس يمر في 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 في طريقة المقارنة وأحصل على NullReferenceException عندما يحاول الوصول إلى أولوية rhs.

هل يمكن أن تخبرني لماذا يحدث هذا وما الذي يجب علي فعله لمعالجة ذلك؟

واسمحوا لي أن أعرف إذا كنت بحاجة إلى أي مزيد من المعلومات.

هل كانت مفيدة؟

المحلول

عندما أقوم بتشغيل التعليمات البرمجية الخاصة بك، أحصل على InvalidOperationException لأن CompareTo لم يتم تنفيذه بشكل صحيح.

لك CompareTo تطبيق يجب يعود 0 لو rhs بالضبط مثل this (أي أن هذا الكائن والكائن الذي تتم مقارنته متساويان).كما لا ينبغي أن تفشل إذا rhs == null, ، ولكن يجب أن تأمر null بطريقة متسقة؛يتم ذلك عادةً عن طريق العودة دائمًا 1 لفرز null قبل كل الكائنات الصالحة.

ال وثائق IComparable.CompareTo يسرد القواعد التالية، التي يجب اتباعها لكي يعمل الفرز بشكل صحيح:

  • A.CompareTo(A) مطلوب لإرجاع الصفر.

  • لو A.CompareTo(B) يعود الصفر، ثمB.CompareTo(A) مطلوب لإرجاع الصفر.

  • لو A.CompareTo(B) إرجاع الصفر وB.CompareTo(C) يعود الصفر، ثمA.CompareTo(C) مطلوب لإرجاع الصفر.

  • لو A.CompareTo(B) إرجاع قيمة أخرى غير الصفر ، ثم B.CompareTo(A)مطلوب لإرجاع قيمة العلامة المعاكسة.

  • لو A.CompareTo(B) إرجاع قيمة x التي لا تساوي الصفر ، وB.CompareTo(C) إرجاع قيمة y من نفس العلامة مثل x ، ثمA.CompareTo(C) مطلوب لإرجاع قيمة نفس العلامة مثل x و y.

لإصلاح المشكلة، تأكد من أن تنفيذك لـ CompareTo يعود 0 عندما priority == rhs.priority && submitted == rhs.submitted.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top