如何使用LINQ和C#使用List更新元素

时间:2010-03-15 18:21:09

标签: c# .net linq ienumerable linq-to-objects

我有一个对象列表,我想更新其中一个对象中的特定成员变量。我知道LINQ是专为查询而设计的,并不意味着更新不可变数据列表。实现这一目标的最佳方法是什么?如果效率不高,我不需要使用LINQ作为解决方案。

创建Update扩展方法是否有效?如果是这样,我该怎么做呢?

EXAMPLE:
(from trade in CrudeBalancedList
 where trade.Date.Month == monthIndex
 select trade).Update(
 trade => trade.Buy += optionQty);

4 个答案:

答案 0 :(得分:30)

尽管linq并不是要更新不可变数据的列表,但是获取要更新的项目非常方便。我想你会这样:

(from trade in CrudeBalancedList
    where trade.Date.Month == monthIndex
    select trade).ToList().ForEach( trade => trade.Buy += optionQty);

答案 1 :(得分:4)

我不确定这是否是最佳方法,但允许您更新列表中的元素。

测试对象:

 public class SomeClass {
        public int Value { get; set; }
        public DateTime Date { get; set; }
    }

扩展方法:

public static class Extension {
        public static void Update<T>(this T item, Action<T> updateAction) {
            updateAction(item);
        }
    }

测试:

public void Test()
{
    // test data
    List<SomeClass> list = new List<SomeClass>()
    {
        new SomeClass {Value = 1, Date = DateTime.Now.AddDays(-1)},
        new SomeClass {Value = 2, Date = DateTime.Now },
        new SomeClass {Value = 3, Date = DateTime.Now.AddDays(1)}
    };
    // query and update
    (from i in list where i.Date.Day.Equals(DateTime.Now.Day) select i).First().Update(v => v.Value += 5);

    foreach (SomeClass s in list) {
        Console.WriteLine(s.Value);
    }
}

答案 2 :(得分:1)

所以你希望在这里得到一个结果。在这种情况下,您可以考虑使用SingleOrDefault方法:

var record =
    (from trade in CrudeBalancedList
    where trade.Date.Month == monthIndex
    select trade).SingleOrDefault();

if (record != null)
    record.Buy += optionQty;

请注意,SingleOrDefault方法需要返回完全一个或零的值(非常类似于表中某些唯一主键的行)。如果返回多个记录,该方法将抛出异常。

答案 3 :(得分:0)

要创建这样的方法,您可以从它的原型开始:

public static class UpdateEx {
    public void Update(this IEnumerable<T> items, 
                       Expression<Action> updateAction) {
    }
}

这很容易。

困难的部分是编译 Expression<Action>到SQL更新语句。根据您希望支持的语法数量,这样的编译器的复杂程度可以从微不足道到不可能。

有关编译Linq表达式的示例,请参阅sqlite-net projectTableQuery类。