أي خطط لـ "do"/Action LINQ Operator؟
سؤال
إليك طريقة بسيطة مع ملف foreach
عقدة:
IEnumerable<XElement> FieldsToXElements(object instance)
{
var fieldElements = new List<XElement>();
foreach (var field in instance.GetType().GetFields(instance))
{
fieldElements.Add(new XElement(field.Name, field.GetValue(instance)));
}
return fieldElements;
}
نوع من القبيح. إذا كان هناك بعض المشغل في LINQ وهذا يعني "افعل شيئًا" (على سبيل المثال ، Action
لكل تم اختياره في عبارة LINQ) ، سيبدو أجمل وأكثر ترويسًا:
IEnumerable<XElement> FieldsToXElements(object instance)
{
var fieldElements = new List<XElement>();
from field in instance.GetType().GetFields(instance))
let name = field.Name
let value = field.GetValue(instance)
do fieldElements.Add(new XElement(name, value));
return fieldElements;
}
أدرك أن هذا شخصي ، ورأيتي فقط. بالنسبة لحلقة foreach التي تحتوي على سطر واحد يستدعي ببساطة طريقة ، "do
"المشغل منطقي ، في رأيي. لكنني أتساءل عما إذا كان أي شخص في MS قد فكر في نفس الشيء. هل تم التخطيط لمشغل LINQ في أي إصدارات قادمة (على سبيل المثال إلى جانب ظهور C# 4.0)؟
إليك مثال آخر ، مع مسند ، حيث الوهمية do
المشغل سيجعل الكود يبدو أنظف. هذه:
IEnumerable<XElement> FieldsToXElements
(object instance, Func<FieldInfo, bool> predicate)
{
var fieldElements = new List<XElement>();
foreach (var field in instance.GetType().GetFields(instance).Where(predicate))
{
fieldElements.Add(new XElement(field.Name, field.GetValue(instance)));
}
return fieldElements;
}
مقابل هذا:
IEnumerable<XElement> FieldsToXElements
(object instance, Func<FieldInfo, bool> predicate)
{
var fieldElements = new List<XElement>();
from field in instance.GetType().GetFields(instance))
let name = field.Name
let value = field.GetValue(instance)
where predicate(field)
do fieldElements.Add(new XElement(name, value));
return fieldElements;
}
المحلول
لا ، لا أتوقع أي مباشرة لغة Suport (أي داخل بناء جملة الاستعلام) في أي وقت قريب.
يبدو أنك تقصد الأسطورية ForEach
طريقة التمديد ؛ تافهة للإضافة ، لكن إريك ليبرت علق عدة مرات حول التقاطع بين الكود الوظيفي الخالي من التأثير و Action<T>
مع الآثار الجانبية. على وجه الخصوص ، فإن أشجار التعبير C# 3.0 / .NET 3.5 رديئة في الآثار الجانبية (مما يجعل دعم Lambda الكامل أمرًا صعبًا). جانب وقت التشغيل أفضل بكثير في .NET 4.0, ، لكن من غير الواضح في الوقت الحالي كم من هذا سيجعله في اللغة (برنامج التحويل البرمجي Lambda) في C# 4.0.
كل ما تحتاجه (لإصدار المندوب) هو:
public static void ForEach<T>(this IEnumerable<T> source, Action<T> action)
{ // note: omitted arg/null checks
foreach(T item in source) { action(item); }
}
ثم من أي استعلام يمكنك استخدامه ببساطة .ForEach(x => /* do something */)
.
نصائح أخرى
للحصول على مثالك المحدد (ملء أ List<XElement>
) ، سأفعل ذلك بهذه الطريقة.
IEnumerable<XElement> FieldsToXElements(object instance)
{
List<XElement> fieldElements =
(
from field in instance.GetType().GetFields(instance))
let name = field.Name
let value = field.GetValue(instance)
select new XElement(name, value)
).ToList(); //Another Option is List<T>.AddRange()
return fieldElements;
}
أيضا: لا تنسى ذلك List<T>
تنفذ بالفعل .ForEach<T>()
, ، لذلك لاستخدامه ضد أي Enumerable<T>
, ، هذا هو كل الرمز الذي تحتاجه.
myEnumerable.ToList().ForEach( x => myAction(x) );
لا أعتقد أن هذا صعب للغاية أو ربما أفتقد شيئًا ...
IEnumerable<XElement> FieldsToXElements(object instance)
{
return instance.GetType()
.GetFields(instance)
.Select( f => new XElement( f.Name,
f.GetValue(instance) ) );
}
إذا كنت تبحث ببساطة في استدعاء وظيفة من داخل بيان LINQ الخاص بك ، فيمكنك القيام بذلك بالفعل ، فيمكنك إجراء استدعاء إلى وظيفة في مهمة Let.
var qry = from e in somelist
let errorcode = DoSomeProcessing(e)
select e;