كيف تستخدم LINQ أساليب iEnumerable بعد طريقة iorderedenumerable؟
-
21-09-2019 - |
سؤال
في 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);