C# 更改列表中的某些值<;T>;

C# 更改列表中的某些值<;T>;,c#,linq,lambda,expression,C#,Linq,Lambda,Expression,我有一些列表(其中T是一个自定义类,类有一些属性)。 我想知道如何使用Lambda表达式更改其中的一个或多个值,因此结果将与下面的foreach循环相同: 注意:列表中包含多个项目(多行) 这是linq查询(使用Lambda表达式),但它与上面的foreach循环不同,它只从列表中返回1项(一行) 我想要的是,它返回所有项(所有行),只更改相应的项(WHERE扩展方法中指定的项) 注意:这两个例子不一样!我重复一遍,linq只返回1个项目(一行),这是我不想要的,我也需要列表中的所有项目(像fo

我有一些列表(其中T是一个自定义类,类有一些属性)。 我想知道如何使用Lambda表达式更改其中的一个或多个值,因此结果将与下面的foreach循环相同:

注意:列表中包含多个项目(多行)

这是linq查询(使用Lambda表达式),但它与上面的foreach循环不同,它只从列表中返回1项(一行)

我想要的是,它返回所有项(所有行),只更改相应的项(WHERE扩展方法中指定的项)

注意:这两个例子不一样!我重复一遍,linq只返回1个项目(一行),这是我不想要的,我也需要列表中的所有项目(像foreach循环一样,它只做更改,但不删除任何项目).

您可以使用,但必须首先将
IEnumerable
转换为
列表

list.Where(w => w.Name == "height").ToList().ForEach(s => s.Value = 30);

您可以将投影与语句lambda一起使用,但是原始的
foreach
循环更具可读性,并且正在原地编辑列表,而不是创建新列表

var result = list.Select(i => 
   { 
      if (i.Name == "height") i.Value = 30;
      return i; 
   }).ToList();
扩展方法

public static IEnumerable<MyClass> SetHeights(
    this IEnumerable<MyClass> source, int value)
{
    foreach (var item in source)
    {
       if (item.Name == "height")
       {
           item.Value = value;
       }

       yield return item;
    } 
}

var result = list.SetHeights(30).ToList();
公共静态IEnumerable设置高度(
此IEnumerable源,int值)
{
foreach(源中的var项)
{
如果(item.Name==“高度”)
{
项目价值=价值;
}
收益回报项目;
} 
}
var result=list.SetHeights(30.ToList();

您可以执行以下操作:

var newList = list.Where(w => w.Name == "height")
              .Select(s => new {s.Name, s.Value= 30 }).ToList();
但是我宁愿选择使用
foreach
,因为
LINQ
是用于在您 想要编辑数据。

我可能会这样做(我知道它不是纯linq),如果您想保留所有项目,请保留对原始列表的引用,您应该会发现更新的值在其中:

 foreach (var mc in list.Where(x => x.Name == "height"))  
     mc.Value = 30;
如何
list.Find(x=>x.Name==“height”)。Value=20;

这很好。我知道这是一篇老文章,但我只是想知道为什么没有人提出这一点?这段代码有缺点吗?

这是我的做法:说“list”是一个
,其中t是一个带有名称和值字段的类;当然,你可以用任何其他类类型来做

    list = list.Where(c=>c.Name == "height")
        .Select( new t(){Name = c.Name, Value = 30})
        .Union(list.Where(c=> c.Name != "height"))
        .ToList();
这是一个没有任何循环逻辑的简单linq表达式。
唯一需要注意的是,结果数据集中的行顺序与源数据集中的行顺序不同。因此,如果排序对您很重要,只需在最终linq查询中复制相同的order by子句即可。

我知道这是一篇旧文章,但我一直使用更新程序扩展方法:

      public static void Update<TSource>(this IEnumerable<TSource> outer, Action<TSource> updator)
        {
            foreach (var item in outer)
            {
                updator(item);
            }
        }

list.Where(w => w.Name == "height").ToList().Update(u => u.height = 30);

公共静态无效更新(此IEnumerable外部操作更新程序)
{
foreach(外部的var项目)
{
更新器(项目);
}
}
list.Where(w=>w.Name==“height”).ToList().Update(u=>u.height=30);


为什么要使用lambda表达式?
foreach
代码运行良好且简单。LINQ用于查询数据,而不是对其进行变异。根据定义,其中只返回匹配的记录。基本上:这不是您想要的-只需使用foreachHi-Jon,我知道foreach循环是否更快速,但我不想学习,仅此而已。因此我“小”代码会很好。但重点主要是学习。Thx Marc,很好且简单的解释。@BluE:但这不是函数式方法。以您想要的形式创建一个新对象是函数式方法。是否可以避免if块?是否可以定义Select扩展方法?是的,您可以定义一个自定义扩展方法,但or原始foreach不那么晦涩,也更容易维护,而且不会创建一个新的列表,这可能会很昂贵。我知道如何使用cusom extemsion方法,我只是想知道是否可以在“短时间”内完成还有,关于代码?!就像@Robin所展示的例子,只是他的代码不起作用!不,满足您的要求并使用LINQ的最短示例是投影和语句lambda,您可以将其封装在自定义扩展方法中,如图所示。SetHeights不应该返回
IEnumerator
而不是
void
?I以前也尝试过这个,但我得到了一个异常:“无效的匿名类型成员声明符。匿名类型成员必须使用成员分配、简单名称或成员访问权限声明。”。这是针对“s.Value=30”。这将创建一个新列表。它会在name!=“height”处截断项目创建一个新列表-它只返回基于WHERE子句的项目。这不是我想要的示例。@MitjaBonca我的错,我误解了你的问题。请参阅上面的编辑。这就是我要查找的内容(如果事件不是最有效的方式,我知道这一点)。使用ForEach可能会导致不稳定的sortif
list.Find(x=>x.Name==“height”)
返回nothing,获取错误
[NullReferenceException:对象引用未设置为对象的实例。]
在实际修改值之前,始终可以执行null检查。不回答问题。这会更改列表中的所有项。
    list = list.Where(c=>c.Name == "height")
        .Select( new t(){Name = c.Name, Value = 30})
        .Union(list.Where(c=> c.Name != "height"))
        .ToList();
      public static void Update<TSource>(this IEnumerable<TSource> outer, Action<TSource> updator)
        {
            foreach (var item in outer)
            {
                updator(item);
            }
        }

list.Where(w => w.Name == "height").ToList().Update(u => u.height = 30);