سؤال

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

IEnumerable<Tab> tabs = GetTabs();

IEnumerable<TabNode> tabNodes = tabs.AsHierarchy().WithStartLevel(2).WithMaxDepth(5);

وهكذا، حول بيان الغلة، وأتساءل عما إذا كان يمكن أن أفعل شيئا من هذا القبيل في صفي NodeHierarchy : IEnumerable<TabNode>:

private IEnumerable<TabNode> _nodes;

public NodeHierarchy(IEnumerable<Tab> tabs)
{
    _nodes = CreateHierarchy(tabs);
}

public IEnumerable<TabNode> CreateHierarchy(IEnumerable<Tab> tabs)
{
    /* About this block: I'm trying to find the top level 
    nodes of the first tab collection, maybe this is done poorly? */
    var tabIds = tabs.Select(t => t.TabID);
    IEnumerable<TabNode> nodes = from tab in tabs
                             where !tabIds.Contains(tab.ParentId)
                                 select new TabNode {
                                            Tab = node,
                                            ChildNodes = CreateHierarchy(tabs, node.TabID, 1),
                                            Depth = 1 };
    return nodes;
}

وأو ما إذا كنت قد تفعل شيئا مثل هذا:

private IEnumerable<TabNode> _nodes;

public NodeHierarchy(IEnumerable<Tab> tabs)
{
    _nodes = CreateHierarchy(tabs);
}

public IEnumerable<TabNode> CreateHierarchy(IEnumerable<Tab> tabs)
{
var tabIds = tabs.Select(t => t.TabID);
IEnumerable<Tab> startingNodes = from tab in tabs
                                 where !tabIds.Contains(tab.ParentId)
                                 select tab;

foreach(Tab node in startingNodes)
{
    yield return
    new TabNode()
        {
        Tab = node,
        ChildNodes = CreateHierarchy(tabs, node.TabID, 1),
        Depth = 1
    };
}
هل كانت مفيدة؟

المحلول

لا، سوف select new لا يؤدي التقييم. وهذه الخريطة لدعوة إلى:

 .Select(tab => new TabNode {...})

ونلاحظ أن Select (لLINQ إلى كائنات، على الأقل) هو في الأساس شيئا مثل:

public static IEnumerable<TDest> Select<TSource,TDest>(
    this IEnumerable<TSource> source,
    Func<TSource,TDest> selector)
{
    foreach(TSource item in source)
    {
        yield return selector(source);
    }
}

والنقطة الأساسية هنا يجري أنه يقيم كسول - ليس في كل مرة

.

وأما النهج ينبغي أن تكون قابلة للمقارنة - والفرق الوحيد هو أنه من دون yield return، <م> بعض سيتم تشغيل كود فورا - ولكن رمز فقط لبناء سلسلة .Where(...).Select(...) - انها لن معالجة الواقع الصفوف حتى بدء بالتكرار النتيجة.

وعلاوة على ذلك، اعتمادا على مصدر البيانات، هذا النهج يمكن فعلا أن تكون أكثر كفاءة - على سبيل المثال، مع الخلفية LINQ إلى SQL، مثل مولد TSQL يمكن تخطي الأعمدة التي لا داعي لها

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