سؤال

قد يكون هذا سؤالًا قديمًا: لماذا IEnumerable<T> ورث من IEnumerable?

هذه هي الطريقة التي تفعل بها .NET ، لكنها تجلب مشكلة صغيرة. في كل مرة أكتب فيها درس IEumerable<T>, ، يجب أن أكتب اثنين GetEnumerator() وظائف ، واحدة ل IEnumerable<T> والآخر ل IEnumerable.

و، IList<T> لا يرث من Ilist.

أنا لا أعرف لماذا IEnumerable<T> تم تصميمه بطريقة أخرى.

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

المحلول

مباشرة من فم الحصان (Hejlsberg):

من الناحية المثالية ، جميع واجهات التجميع العامة (على سبيل المثال ICollection<T>, IList<T>) سوف يرث من نظرائهم غير العامين بحيث يمكن استخدام مثيلات الواجهة العامة مع رمز عام وغير عام. على سبيل المثال ، سيكون من المريح إذا IList<T> يمكن نقلها إلى رمز يتوقع IList.

كما اتضح ، الواجهة العامة الوحيدة التي يمكن أن يكون ذلك ممكنًا IEnumerable<T>, ، لأن فقط IEnumerable<T> متغير: في IEnumerable<T>, ، يتم استخدام المعلمة T -type T فقط في مواضع "الإخراج" (قيم الإرجاع) وليس في مواضع "الإدخال" (المعلمات). ICollection<T> و IList<T> استخدم T في كل من مواضع الإدخال والمخرجات ، وبالتالي فإن تلك الواجهات ثابتة. (جانبا ، كان من الممكن أن يكونوا متغيرين إذا تم استخدام T فقط في مواقف الإدخال ، لكن هذا لا يهم هنا.)

<... snip ...>

لذا ، للإجابة على سؤالك ، IEnumerable<T> يرث من IEnumerable لأنه يمكن! :-)

نصائح أخرى

الجواب ل IEnumerable هو: "لأنه لا يمكن أن تؤثر على سلامة النوع".

IEnumerable هي واجهة "Readonly" - لذلك لا يهم أن يكون النموذج العام أكثر تحديداً من النموذج nongeneric. أنت لا تكسر أي شيء عن طريق تنفيذ كليهما. IEnumerator.Current عائدات object, ، بينما IEnumerator<T>.Current عائدات T - لا بأس ، حيث يمكنك دائمًا التحويل بشكل شرعي object, ، على الرغم من أنه قد يعني الملاكمة.

قارن هذا مع IList<T> و IList - تستطيع الاتصال Add(object) على IList, ، في حين أن هذا قد يكون غير صالح لأي معين IList<T> (أي شيء آخر غير IList<object> في الواقع).

براد أبرام تم التدوين مع إجابة Anders حول هذا السؤال بالذات.

إنه للتوافق المتخلف. إذا اتصلت بوظيفة .NET 1.1 التي تتوقع حدوث فانيليا غير قابلة للانتقال في ienumerable.

Luckilly يرث ienumerator عام من Ienumerator على الطراز القديم

عادةً ما أقوم بتطبيق طريقة خاصة تُرجع العداد ثم تمريرها لكل من طريقة GetEnumerator القديمة والجديدة.

    private IEnumerator<string> Enumerator() {
        // ...
    }

    public IEnumerator<string> GetEnumerator() {
        return Enumerator();
    }

    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() {
        return Enumerator();
    }

هذا حتى أنه سيعمل مع فصول لا تدعم الأدوية الجيرية. بالإضافة إلى ذلك ، لا تسمح لك genericsu003Clong> كما ilistu003Cint> ، يمكن أن تكون الإصدارات غير العامة من الواجهات مفيدة للغاية عندما تحتاج إلى فئة أو واجهة قاعدة ثابتة.

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