سؤال

لدي البرمجية التالية

class Program
    {
        static void Main(string[] args)
        {
            List<A> aList = new List<A>();

            var aObj = new A();

            aObj.Go(aList.Cast<IB>());
        }
    }

    class A : IB
    {
        public void Go(IEnumerable<IB> interfaceList)
        {
            foreach (IB ibby in interfaceList)
            {
                Console.WriteLine("Here");
            }
        }
    }

    interface IB
    {
        void Go(IEnumerable<IB> interfaceList);
    }

}

أنا أصلا حاولت تمرير قائمة ولكن هذا لا يعمل.بعد الكثير من المساعدة من لذلك وجدت أن يمر IEnumerable هو السبيل الوحيد للحصول على الأشياء عبر .ofType(IB).

لسوء الحظ بالنسبة لي في بلدي رمز السطر التالي وسيتم تنفيذ آلاف المرات:

aList.Cast<IB>();

أنا أتساءل عما إذا كان أي شخص يعرف كيف تم تنفيذه حسابيا (IL) و ما لها وقت النظام.

وهذا هو القول ، هو أسرع من حلقة foreach فقط أن يلقي كل بند ، أو أن هذا بالضبط ما يقوم به ؟

تحرير الطبقة الرئيسية يحتاج إلى الحفاظ على قائمة من الكائنات الفعلية.ولكن القارئ هو فقط يسمح للمس لهم من خلال واجهة.

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

المحلول

يجب تغيير Go إلى:

public void Go<T>(IEnumerable<T> interfaceList)
    where T : IB
{
    foreach (IB ibby in interfaceList)
    {
        Console.WriteLine("Here");
    }
}

ثم سوف يكون على ما يرام دون الحاجة إلى الاتصال Cast.وأظن شفرة المصدر تنفيذ يلقي بسيطة جدا, على الرغم من أنني أعتقد أنه تغير بين 3.5 و3.5SP1.ومع ذلك ، فإنه قد يحتاج إلى اقامة دولة جديدة آلة الخ في العادي مكرر كتلة الموضة.من الأفضل تجنب ذلك إذا كان ذلك ممكنا.

على الرغم من الأسلوب الجديد هو عام, نوع الاستدلال أن عادة ما تأخذ الرعاية من ذلك بالنسبة لك إذا كنت لا تحتاج إلى تحديد T صراحة.

نصائح أخرى

لماذا لا يعلن قائمة مثل:

List<IB> aList = new List<IB>();

هل هناك شيء على وجه الخصوص الذي يتطلب أن يكون لديك قائمة من الخرسانة الطبقات ؟


حتى في هذه الحالة سوف تجعل قائمة جزءا من هذا المجال.يكون واجهة مثل IIBCollection (على سبيل المثال) ، فضح الأساليب التي تريد للقارئ أن تكون قادرة على الوصول.على سبيل المثال:

interface IIBCollection{
    IEnumerable<IB> IBs { get; }
}

// and in your implementation you can do

IEnumerable<IB> IBs { 
    get { 
        foreach(IB ib in innerList) yield return ib; 
}}

انها تنفذ داخليا كما CastIterator الذي هو أبطأ قليلا من foreach أن يلقي كل بند.

الزهر الطريقة سوف مجرد حلقة من خلال قائمة ويلقي كل بند.

إذا كنت تنوي استخدام قائمة الآلاف من الوقت فقط مخزن نتيجة الصب على شكل قائمة.

إذا كان هذا غير ممكن (أييمكنك تغيير القائمة في كل مرة) ، النظر في العمل مع List<IB> بدلا من List<A>.

أليس هذا ما التغاير في C# ؟ أنا لا أرى ما كنت تحاول القيام به ، لذلك لا أستطيع التعليق على السبب في أنه من exeuted آلاف المرات.

ستكون مسألة بسيطة إلى حد ما فقط لقياس طريقتين (الزهر طريقة التمديد و حلقة مع المدلى بها).ولكن بالنظر إلى أن يلقي هو امتداد طريقة Enumerable فئة تتعامل بشكل عام مع IEnumerables أتخيل هذا هو بالضبط التنفيذ.إذا كنت تريد أعظم السرعة ، قد يكون من الأفضل لتنفيذ الخاصة بك امتداد الأسلوب الذي يعمل على وجه التحديد على قائمة (يحصل كل عنصر من قبل مؤشر), التي ينبغي أن تكون أسرع قليلا بالنظر إلى النفقات العامة من التكرار.لا يزال كلا الأسلوبين ينبغي أن تأخذ O(n) الوقت ، وبالتالي فإن الاختلاف لا يجب أن تكون ضخمة.انها شيء يستحق المقارنة مع ذلك...

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