سؤال

ممكن مكررة:
لماذا هناك لا ForEach طريقة التمديد على IEnumerable واجهة ؟

لقد لاحظت عند كتابة ينق ذ التعليمات البرمجية التي .ForEach() هو لطيف المصطلح إلى استخدام.على سبيل المثال, هنا هو قطعة من التعليمات البرمجية التي تأخذ المدخلات التالية ، وتنتج هذه النواتج:

{ "One" } => "One"
{ "One", "Two" } => "One, Two"
{ "One", "Two", "Three", "Four" } => "One, Two, Three and Four";

و رمز:

private string InsertCommasAttempt(IEnumerable<string> words)
{
    List<string> wordList = words.ToList();
    StringBuilder sb = new StringBuilder();
    var wordsAndSeparators = wordList.Select((string word, int pos) =>
        {
            if (pos == 0) return new { Word = word, Leading = string.Empty };
            if (pos == wordList.Count - 1) return new { Word = word, Leading = " and " };
            return new { Word = word, Leading = ", " };
        });

    wordsAndSeparators.ToList().ForEach(v => sb.Append(v.Leading).Append(v.Word));
    return sb.ToString();
}

ملاحظة سجلتها .ToList() قبل .ForEach() في الثاني إلى السطر الأخير.

لماذا .ForEach() لا تستخدم الأسلوب على IEnumerable<T>?مع مثال على مثل هذا يبدو غريبا.

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

المحلول

لأن ForEach(Action) كانت موجودة قبل IEnumerable<T> كانت موجودة.

لأنه لا تضاف مع أساليب الإرشاد الأخرى ، يمكن للمرء أن نفترض أن C# المصممين شعرت سيئة التصميم و تفضل foreach بناء.


تحرير:

إذا كنت تريد يمكنك إنشاء الخاصة بك طريقة التمديد لن تجاوز واحد List<T> ولكن سوف تعمل على أي فئة أخرى التي تنفذ IEnumerable<T>.

public static class IEnumerableExtensions
{
  public static void ForEach<T>(this IEnumerable<T> source, Action<T> action)
  {
    foreach (T item in source)
      action(item);
  }
}

نصائح أخرى

وفقا إريك ليبرت ، وهذا هو في الغالب لأسباب فلسفية.يجب عليك قراءة كاملة وظيفة, ولكن هنا هو جوهر بقدر ما أنا قلق:

أنا فلسفيا بدلا من وتوفير مثل هذا الأسلوب ، الأسباب.

السبب الأول هو أن القيام بذلك ينتهك البرمجة الوظيفية المبادئ التي سائر تسلسل شركات تقوم على أساس.بوضوح الغرض الوحيد من الدعوة إلى هذا الأسلوب هو أن تتسبب في آثار جانبية.

الغرض من التعبير هو حساب قيمة لا يسبب الجانب تأثير.والغرض من هذا البيان هو أن يتسبب في آثار جانبية.الاتصال الموقع هذا الشيء سوف تبدو الكثير مثل تعبير (على الرغم من ، باعتراف الجميع, لأن الأسلوب هو الفراغ-العودة, التعبير قد إلا أن استخدامها في "بيان التعبير" السياق.)

لا الجلوس بشكل جيد مع لي لجعل واحد فقط تسلسل المشغل هذا مفيد فقط في جانبها الآثار.

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

لأن ForEach() على IEnumerable هو مجرد الطبيعي لكل حلقة مثل هذا:

for each T item in MyEnumerable
{
    // Action<T> goes here
}

أنا فقط أخمن هنا , ولكن وضع foreach على IEnumerable من شأنه أن يجعل العمليات عليها أن يكون لها آثار جانبية .أي من "المتاحة" طرق الإرشاد تتسبب في آثار جانبية ، ووضع حتمية طريقة مثل foreach هناك من شأنه تعكير api أعتقد .أيضا ، foreach من شأنه تهيئة كسول جمع .

شخصيا لقد تم صد إغراء فقط إضافة بلدي , فقط للحفاظ على الآثار الجانبية الحرة وظائف منفصلة عن تلك الآثار الجانبية.

ForEach ليس على IList انه على القائمة.كنت تستخدم الخرسانة القائمة في المثال الخاص بك.

أنا بصراحة لا أعرف على وجه اليقين لماذا .ForEach(العمل) ليست مدرجة على IEnumerable ولكن الحق ، خاطئة أو غير مبال ، هكذا هو...

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

class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine("Start Loop timing test: loading collection...");
        List<int> l = new List<int>();

        for (long i = 0; i < 60000000; i++)
        {
            l.Add(Convert.ToInt32(i));
        }

        Console.WriteLine("Collection loaded with {0} elements: start timings",l.Count());
        Console.WriteLine("\n<===============================================>\n");
        Console.WriteLine("foreach loop test starting...");

        DateTime start = DateTime.Now;

        //l.ForEach(x => l[x].ToString());

        foreach (int x in l)
            l[x].ToString();

        Console.WriteLine("foreach Loop Time for {0} elements = {1}", l.Count(), DateTime.Now - start);
        Console.WriteLine("\n<===============================================>\n");
        Console.WriteLine("List.ForEach(x => x.action) loop test starting...");

        start = DateTime.Now;

        l.ForEach(x => l[x].ToString());

        Console.WriteLine("List.ForEach(x => x.action) Loop Time for {0} elements = {1}", l.Count(), DateTime.Now - start);
        Console.WriteLine("\n<===============================================>\n");

        Console.WriteLine("for loop test starting...");

        start = DateTime.Now;
        int count = l.Count();
        for (int i = 0; i < count; i++)
        {
            l[i].ToString();
        }

        Console.WriteLine("for Loop Time for {0} elements = {1}", l.Count(), DateTime.Now - start);
        Console.WriteLine("\n<===============================================>\n");

        Console.WriteLine("\n\nPress Enter to continue...");
        Console.ReadLine();
    }

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

ForEach يتم تنفيذها في فئة محددة List<T>

مجرد تخمين لكن القائمة يمكن أن يكرر أكثر من بنودها دون خلق العداد:

public void ForEach(Action<T> action)
{
    if (action == null)
    {
        ThrowHelper.ThrowArgumentNullException(ExceptionArgument.match);
    }
    for (int i = 0; i < this._size; i++)
    {
        action(this._items[i]);
    }
}

هذا يمكن أن يؤدي إلى أداء أفضل.مع IEnumerable ليس لديك خيار استخدام عادي على حلقة.

انه دعا "حدد" على IEnumerable<T> أنا المستنير ، شكرا لك.

LINQ يلي سحب نموذج وجميع (ملحق) أساليب يجب أن تعود IEnumerable<T>, باستثناء ToList().على ToList() هناك إلى حد سحب السلسلة.

ForEach() هو من دفع نموذج العالم.

لا يزال بإمكانك الكتابة الخاصة بك تمديد طريقة للقيام بذلك ، كما أشار صموئيل.

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