Where 和 Select 的方法链中的 Linq 中间对象?

Linq Intermediate Object in method chain for Where and Select?

我正在处理DocumentFormat.xml。

我需要做一些工作来获取 where 子句所需的数据。

但是我需要在 where 子句中做同样的工作来构造所需的对象。

这看起来很浪费。

有没有更好的构造方法?

var rowData = registersRows
    .Where(row =>
    {
        var cells = row.Elements<Cell>().ToList();
        return included.Contains(GetCellText(cells, "A", row.RowIndex, sharedStringTableItems));
    })
    .Select(row =>
    {
        var cells = row.Elements<Cell>().ToList();
        return new RegistersRow
        {
            StoreNumber = GetCellText(cells, "A", row.RowIndex, sharedStringTableItems),
            ChannelName = GetCellText(cells, "D", row.RowIndex, sharedStringTableItems),
            ChannelDisplayName = GetCellText(cells, "E", row.RowIndex, sharedStringTableItems),
            PhysicalDeviceName = GetCellText(cells, "F", row.RowIndex, sharedStringTableItems),
            FriendlyName = GetCellText(cells, "G", row.RowIndex, sharedStringTableItems),
            DisplayNameInLabel = GetCellText(cells, "H", row.RowIndex, sharedStringTableItems),
            NumberOfRegisters =
                int.Parse(GetCellText(cells, "K", row.RowIndex, sharedStringTableItems))
        };
    }).ToList();

具体在这个例子中我需要提取StoreNumber并获取两次Cells。

如果您将 LINQ 与查询语法一起使用,则您可以使用 let 关键字创建一个临时文件以供稍后在查询中使用。当编译器将查询语法转换为 fluent/lambda 语法时,let 将转换为 Select,它将临时值与您需要携带到未来方法中的任何值捆绑在一起。

您可以手动执行相同操作:

var rowData = registersRows
    .Select(r => new { RowIndex = r.RowIndex, cells = r.Elements<Cell>().ToList() })
    .Select(rc => new { rc.RowIndex, rc.cells, A = GetCellText(rc.cells, "A", rc.RowIndex, sharedStringTableItems) })
    .Where(rca => included.Contains(rca.A))
    .Select(rca => new RegistersRow {
        StoreNumber = rca.A,
        ChannelName = GetCellText(rca.cells, "D", rca.RowIndex, sharedStringTableItems),
        ChannelDisplayName = GetCellText(rca.cells, "E", rca.RowIndex, sharedStringTableItems),
        PhysicalDeviceName = GetCellText(rca.cells, "F", rca.RowIndex, sharedStringTableItems),
        FriendlyName = GetCellText(rca.cells, "G", rca.RowIndex, sharedStringTableItems),
        DisplayNameInLabel = GetCellText(rca.cells, "H", rca.RowIndex, sharedStringTableItems),
        NumberOfRegisters =
                int.Parse(GetCellText(rca.cells, "K", rca.RowIndex, sharedStringTableItems))
    })
    .ToList();