解释这个LINQ代码?

时间:2009-04-30 17:27:00

标签: c# .net linq

我问了一个问题,其中一个响应包含以下LINQ代码:

var selected = lstAvailableColors.Cast<ListItem>().Where(i => i.Selected).ToList();
selected.ForEach( x => { lstSelectedColors.Items.Add(x); });
selected.ForEach( x => { lstAvailableColors.Items.Remove(x);});

有人可以解释上面的LINQ到新手吗?

4 个答案:

答案 0 :(得分:5)

LINQ运算符使用所谓的fluent interface,因此您可以将第一行读作一系列函数调用。假设lstAvailableColorsIEnumerable<T>,我们的想法是每个可用的颜色都流经LINQ运算符。

让我们分解一下:

var selected = lstAvailableColors
    // each item is cast to ListItem type
    .Cast<ListItem>() 
    // items that don't pass the test (Selected == true) are dropped
    .Where(i => i.Selected) 
    // turn the stream into a List<ListItem> object
    .ToList();

编辑:正如JaredPar指出的那样,上面的最后一行(ToList())非常重要。如果您没有这样做,那么两个selected.ForEach调用中的每一个都将重新运行查询。这称为deferred execution,是LINQ的重要组成部分。

您可以像这样重写第一行:

var selected = new List<ListItem>();

foreach (var item in lstAvailableColors)
{
    var listItem = (ListItem)item;

    if (!listItem.Selected)
         continue;

    selected.Add(listItem);
}

最后两行只是编写foreach循环的另一种方式,可以重写为:

foreach (var x in selected)
{
    lstSelectedColors.Items.Add(x);
}

foreach (var x in selected)
{
    lstAvailableColors.Items.Remove(X);
}

学习LINQ最困难的部分可能是学习数据流和lambda expressions的语法。

答案 1 :(得分:3)

原始问题的解释。

LINQ版本分为两部分。第一部分是第一行,它找到当前选定的项目并将值存储在List中。该行包含.ToList()调用非常重要,因为这会强制查询立即执行而不是延迟执行。

接下来的两行迭代选中的每个值,然后将其删除或添加到相应的列表中。因为已经存储了所选列表,所以当我们修改它时,我们不再枚举该集合。

答案 2 :(得分:2)

它将列表中的每个项目转换为ListItem类型,然后仅选择其Selected属性为true的项目。然后它创建一个仅包含这些项目的新列表。对于结果列表中的每个项目,它会将该项目添加到所选颜色列表中,并将其从可用颜色列表中删除。

答案 3 :(得分:1)

也许有些翻译会有所帮助

var selected = lstAvailableColors.Cast<ListItem>().Where(i => i.Selected).ToList();

可以写成:

List<ListItem> selected = new List<ListItem>();

foreach (ListItem item in lstAvailableColors)
{
    if (item.Selected)
        selected.Add(item);
}

请注意,foreach隐式地将列表中的项目转换为循环变量的任何类型,在本例中为ListItem,以便处理列表中的Cast<ListItem>Where过滤掉表达式为false的所有项目,因此我使用if语句执行相同的操作。最后,ToList将序列转换为列表,所以我只是建立一个列表。最终结果是一样的。

selected.ForEach( x => { lstSelectedColors.Items.Add(x); });
selected.ForEach( x => { lstAvailableColors.Items.Remove(x); });

可以写成:

foreach (ListItem item in selected)
{
    lstSelectedColors.Items.Add(item);
    lstAvailableColors.Items.Remove(item);
}

我怀疑在这种情况下是否有充分的理由将其写成更为模糊的方式。