foreach، الأداء الحكيم.هل يجب أن نعلن عن المتغير مرة واحدة قبل الحلقة أم داخلها؟

StackOverflow https://stackoverflow.com/questions/1632444

  •  06-07-2019
  •  | 
  •  

سؤال

ما هو أفضل للأداء من الحكمة إعلان المتغير خارج إحصاء foreach وأحد مرة إعادة تعيينه في جنب

private List<ListItem> GetItems()
        {
            var items = new List<ListItem>();
            var collection = new List<int> { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
            ListItem item;
            foreach (var i in collection)
            {
                item = new ListItem { Text = i.ToString() };
                items.Add(item);
            }

            return items;
        }

ما سر جديدة هذا؟

private List<ListItem> GetItems()
        {
            var items = new List<ListItem>();
            var collection = new List<int> { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
            foreach (var i in collection)
            {
                ListItem item = new ListItem { Text = i.ToString() };
                items.Add(item);
            }

            return items;
        }

بالتأكيد أنا هنا أتحدث عن كائن العنصر.شكرا لكم جميعا.

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

المحلول

هذا يبدو وكأنه التحسين المبكر.

بداية، هل لديك أي سبب للاعتقاد بوجود مشكلة في الأداء هنا؟

ثانياً، في إصدارات الإصدار، من المحتمل أن يقوم مُحسِّن المترجم بإنتاج تعليمات برمجية متطابقة لكلا السيناريوهين - لذا فهو على الأرجح غير ذي صلة.في عمليات إنشاء تصحيح الأخطاء، قد لا يكون هذا صحيحًا دائمًا، ولكنك لا تريد إجراء تحسينات لأن الهدف من إنشاءات تصحيح الأخطاء هو السماح لك بالتنقل بدقة خلال التعليمات البرمجية.

نصائح أخرى

وهناك هو حالة الحافة حيث هذه الأمور؛ إذا كنت "الاستيلاء" على متغير إلى أسلوب مجهول / امدا. وإلا فإنه من السابق لأوانه ولا فرق. على الإطلاق.

ومثال على ذلك عندما يهم:

// prints all items in no particular order
foreach (var i in collection)
{
    string s = i.ToString();
    ThreadPool.QueueUserWorkItem(delegate { Console.WriteLine(s); });
}

ومقابل

// may print the same item each time, or any combination of items; very bad
string s;
foreach (var i in collection)
{
    s = i.ToString();
    ThreadPool.QueueUserWorkItem(delegate { Console.WriteLine(s); });
}

وأنا متأكد من IL لدت قبل اثنين من كتل التعليمات البرمجية غير متطابقة. لا ينبغي أن يكون هناك أي تغيير في الأداء. لكن كتلة التعليمات البرمجية الثاني حيث قمت بتعريف نوع العنصر الحق حيث يتم استخدامه قليلا أكثر قابلية للقراءة وأود أن استخدام ذلك.

وهذا هو الأمثل للغاية الصغير، وسوف كلتا الطريقتين من المرجح أن تكون بالضبط نفس الأداء الحكمة، إن لم يكن توليد كود متطابقة. في هذه الحالة، انتقل للقراءة. كنت تفضل الثانية، منذ الكائن لا يخدم أي غرض خارج حلقة foreach.

ويمكن القول، هل يمكن أيضا التخلص من الإشارة المخزنة معا:

private List<ListItem> GetItems()
{
  var items = new List<ListItem>();
  var collection = new List<int> { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };

  foreach (var i in collection)
  {
    items.Add(new ListItem { Text = i.ToString() });
  }

  return items;
}

ووIL إنشاؤها من قبل الكتلتين يجب أن يكون نفسه تقريبا. إذا كنت تبحث لتحسين، وأود أن ننظر في تحديد طول من القائمة النهائية قبل ملئه مع العناصر. بهذه الطريقة فلن تكون عقوبة التوسع لتمديد مدة القائمة.

وشيء من هذا القبيل:

  private List<ListItem> GetItems()
    {
        var collection = new List<int> { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
        var items = new List<ListItem>(collection.Count);  //declare the amount of space here

        foreach (var i in collection)
        {
            ListItem item = new ListItem { Text = i.ToString() };
            items.Add(item);
        }

        return items;
    }

ويجمع ربما لنفس رمز ولكن لماذا تهتم redeclaring ذلك. وهذا هو الشيء الجميل الإشارة في هذا البند القضية. وبمجرد الانتهاء من ذلك مع أنه يمكنك تعيينه إلى عنصر القائمة آخر وGC يعتني بقية.

ولكن على قراءة أوثيرهاند للمبرمجين الآخرين. انه قرار الذي بالتأكيد لن تغيير جذري في أداء التطبيقات الخاصة بك.

وحتى أفضل في حالتك هو:

private List<ListItem> GetItems()        
{            
   var items = new List<ListItem>();            
   var collection = new List<int> { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };            
   foreach (var i in collection)            
      items.Add(new ListItem { Text = i.ToString() });                 
   return items;        
}

لماذا إنشاء متغير إضافي على الإطلاق؟

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

ونطاق وسياق تلك الكتلة من التعليمات البرمجية أكثر أهمية من تحسينات الأداء الصغيرة التي سيكون من السابق لأوانه في الطبيعة وغير ضرورية في هذا السيناريو.

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