سؤال

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

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

وبعبارة أخرى، يمكنني القيام بذلك:

from si in (i.subitems == null ? new List<item>() : i.subitems)

ولكن هذا قبيح قليلا وتساءلت كيف يمكنني تحسين ذلك؟

public class item
{
    public string itemname { get; set; }
    public List<item> subitems { get; set; }
}

void Main()
{
    List<item> myItemList = new List<item>() 
    {
        new item 
        {
            itemname = "item1",
            subitems = new List<item>()
            {
                new item { itemname = "subitem1" },
                new item { itemname = "subitem2" }
            }
        },
        new item 
        {
            itemname = "item2"
        }
    };

    myItemList.Dump();

    var res = (from i in myItemList
            from si in i.subitems
            select new {i.itemname, subitemname = si.itemname}).ToList();

    res.Dump();
}

كمسحة مكافأة، هل يمكن تمثيل هذا الاستعلام Linq نفسه كامدا وعلاجه خيال بنفس الطريقة؟

هتاف، كريس

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

المحلول

يمكنك استخدام غير فارغ من المشغل

var res = (from i in myItemList
           from si in i.subitems ?? new List<item>()
           select new { i.itemname, subitemname = si.itemname }).ToList();

لكنني أعتقد أنك يجب عليك فقط تصفية تلك الفارغة

var res = (from i in myItemList
           where i.subitems != null
           from si in i.subitems
           select new { i.itemname, subitemname = si.itemname }).ToList();

بالنسبة لإصدار Lambda، يمكنك القول

var res = myItemList.Where(x => x.subitems != null)
                    .SelectMany(
                        x => x.subitems.Select(
                            y => new { x.itemname, subitemname = y.itemname }
                        )
                     );

ولكن إصدار بناء جملة الاستعلام هو الطريق أكثر قراءة.

نصائح أخرى

from si in (i.subitems ?? new List<item>())

ماذا عن ذلك؟

يمكنك إضافة طريقة تمديد (شر) للقيام بالعمل بالنسبة لك

public static IEnumerable<T> EnsureNotEmpty<T>(this IEnumerable<T> enumerable) {
  if ( enumerable == null ) {
    return Enumerable.Empty<T>();
  } else { 
    return enumerable;
  }
}

لن تكون الطريقة الإضافية لا تسمح بدفعها إلى أن تكون فارغة. يمكنك جعل منشئ العنصر بحيث افتراضي تحديد الفرعية إلى قائمة فارغة، ثم لا يسمح ب Null في Setter Subitem.

ينفص ذلك بالطبع لديك إمكانية الوصول إلى تعديل العنصر.

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

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