可以在LINQ / lambda中重写下面的代码

时间:2011-04-07 08:42:32

标签: c# .net linq lambda

以下代码可以通过LINQ或lambda来改进:

foreach (var item in listItem)
{
    var dataRow = dataTable.NewRow();
    foreach (var col in dataTableColumnNames)
    {
        var p = listType.GetProperty(col);
        if (p != null)
        {
            dataRow[col] = p.GetValue(item, null);
        }
    }   
    dataTable.Rows.Add(dataRow);
}

虽然在程序中没有任何问题,但我想要感受一下LINQ / lambda。

4 个答案:

答案 0 :(得分:4)

由于你的代码片段在其循环中调用语句(在内部循环中进行赋值并在外部调用Rows.Add()),因此使用LINQ不是一个非常好的方案。

如果您仍然希望以更“实用”的方式编写它,那么您可能做的最好的方法是使用ForEach()扩展方法而不是循环,但代码仍然会完全相同并且会实际上并没有真正使用LINQ。

在这里尝试使用LINQ非常困难,你最终会得到类似的东西:

listItem
    .Select(item => 
        {
            var dataRow = dataTable.NewRow();
            dataTableColumnNames
               .Select(col => listType.GetProperty(col))
               .Where(p => p != null)
               .ForEach(p => dataRow[p.Name] = p.GetValue(item, null));
            return row;
        })
    .ForEach(row => dataTable.Rows.Add(row));

我在这里使用属性的p.Name代替col来使这更简单,但一般功能应该是相同的。正如其他答案所述,这也不会提高可读性。

请注意,普通的LINQ中不包含ForEach()扩展方法,如果您还没有,则必须自己编写。

答案 1 :(得分:1)

我认为您还应该考虑可读性,特别是如果您的代码将来可能会发生变化。使用lamba表达式,你的代码不会有太大的改进,并且更难理解。

答案 2 :(得分:1)

正如你写的那样,没有。使用正确的方法,你可以在这里使用一些 LINQ,你只需要编写代码以方便其使用。这里,LINQ可用于收集要添加到表中的数据。然后使用循环将它们全部添加。

// let's create the table and its columns
var dataTable = new DataTable("My Table");
dataTable.Columns
         .AddRange(new[] { "Name", "Address" }
                       .Select(n => new DataColumn(n))
                       .ToArray());

// the items to be added
var items = new[]
{
    new { Name = "Bob", Address = "Foo Street" },
    new { Name = "Joe", Address = "Bar Road" },
    new { Name = "Jon", Address = "Baz Avenue" },
};

var itemType = items.GetType().GetElementType();
var rowDatas =
    items.Select(item =>
        from col in dataTable.Columns.Cast<DataColumn>()
        let prop = itemType.GetProperty(col.ColumnName)
        select new
        {
            col.ColumnName,
            Value = prop != null
                ? prop.GetValue(item, null)
                : null,
        });

foreach (var rowData in rowDatas)
{
    var row = dataTable.NewRow();
    foreach (var cell in rowData)
        row[cell.ColumnName] = cell.Value;
}

但是,您可以滥用它并利用在表的行集合上使用Add()方法向数据表添加行的副作用。你通常不应该这样做,但它确实使事情变得更紧凑。

var itemType = items.GetType().GetElementType();
items.Select(item =>
    dataTable.Rows.Add( // create and add a new row with the following values
        dataTable.Columns
            .Cast<DataColumn>()
            .Select(col => itemType.GetProperty(col.ColumnName))
            .Select(prop => prop != null ? prop.GetValue(item, null) : null)
            .ToArray()
        )
    ).ToList(); // "execute" this thing

答案 3 :(得分:0)

我会在进入循环之前得到属性信息。我假设listItem的类型为List<T>

var properties = dataTableColumnNames
        .Select(listItemType.GetProperty)
        .OfType<PropertyInfo>() // drop null values
        .ToList();

listItems.ForEach(item => {
    var dataRow = dataTable.NewRow();
    properties.ForEach(property =>
            dataRow[property.Name] = property.GetValue(item, null));
    dataTable.Rows.Add(dataRow);
});