كيف تستخدم LINQ أساليب iEnumerable بعد طريقة iorderedenumerable؟

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

سؤال

في LINQ ، مثل طرق التمديد Where إرجاع IEnumerable جمع ، ولكن طرق الفرز مثل OrderBy إرجاع IOrderedEnumerable مجموعة.

لذا ، إذا كان لديك استعلام ينتهي OrderBy (أي إرجاع IOrderedEnumerable) ، لا يمكنك لاحقًا إلحاق أ Where الطريقة - يشكو المترجم من النوع الذي يتم نقله إلى Where.

var query = Process.GetProcesses()
            .Where(p => p.ProcessName.Length < 10)
            .OrderBy(p => p.Id);

query = query.Where(p => p.ProcessName.Length < 5);

ومع ذلك ، إذا فعلت كل شيء في استفسار واحد ، فلا بأس!

var query = Process.GetProcesses()
            .Where(p => p.ProcessName.Length < 10)
            .OrderBy(p => p.Id)
            .Where(p => p.ProcessName.Length < 5);

لقد نظرت إلى التجمع في Reflector لمعرفة ما إذا كان المترجم يعيد ترتيب أي من العمليات ، لكن لا يبدو أن الأمر كذلك. كيف يعمل هذا؟

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

المحلول

IOrderedEnumerable<T> يمتد IEnumerable<T> لذلك لا يزال بإمكانك استخدام أي من طرق التمديد. السبب في أن أول كتلة من الكود لم تنجح هو أنك كتبت بشكل فعال:

IOrderedEnumerable<Process> query = Process.GetProcesses()
                                           .Where(p => p.ProcessName.Length < 10)
                                           .OrderBy(p => p.Id);

// Fail: can't assign an IEnumerable<Process> into a variable 
// of type IOrderedEnumerable<Process>
query = query.Where(p => p.ProcessName.Length < 5);

هذا فشل بسبب query.Where(...) يعود فقط IEnumerable<Process>, ، والتي لا يمكن تعيينها إلى query عامل. إنه لا يتصل Where هذه هي المشكلة - إنها تعين النتيجة مرة أخرى إلى المتغير الأصلي. لإثبات ذلك ، سيعمل هذا الرمز على ما يرام:

var query = Process.GetProcesses()
                   .Where(p => p.ProcessName.Length < 10)
                   .OrderBy(p => p.Id);

// Introduce a new variable instead of trying to reuse the previous one
var query2 = query.Where(p => p.ProcessName.Length < 5);

بدلاً من ذلك ، يمكنك إعلان الاستعلام ليكون IEnumerable<T> لتبدأ:

IEnumerable<Process> query = Process.GetProcesses()
                                    .Where(p => p.ProcessName.Length < 10)
                                    .OrderBy(p => p.Id);

// Fine
query = query.Where(p => p.ProcessName.Length < 5);
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top