使用linq更改list's属性
本文关键字:属性 linq 更改 list 使用 | 更新日期: 2023-09-27 18:03:42
如何使下面的代码更短,可能使用匿名方法或扩展和LINQ
.
因为我必须重复这段代码几次,我想使它尽可能简洁。
var imagesToUnlock = App.ImageListVM.Items.Where(img => img.Category == key);
foreach (var image in imagesToUnlock)
{
image.IsLocked = false;
}
这里的其他解决方案感觉很脏,因为它们通过使用LINQ来改变集合中的对象。
我将把代码和筛选条件放入一个扩展方法中,并调用它:public static IEnumerable<Item> UnlockWhere(this IEnumerable<Item> list, Func<Item, bool> condition) {
foreach (var image in list)
if (condition(image)) {
image.IsLocked = false;
yield return image;
}
}
保持了LINQ的不变性,并且仍然产生预期的结果。
调用变成:
var unlockedItems = App.ImageListVM.Items.UnlockWhere(img => img.Category == key);
编辑
重写以完全删除LINQ。相反,这个新方法只迭代一次,并返回一个新的变异集合。
这不是最有效的方法,但我相信你能做到
var imagesToUnlock = App.ImageListVM.Items.Where(img => img.Category == key).ToList().Foreach(f => f.IsLocked = false);
查看List<T>
上的Foreach方法以获取更多信息。
我还想指出(正如一些人在评论中指出的那样),有些人认为这不是最佳实践。您应该看看Eric Lippert的这篇文章,他更详细地解释了这个问题。
这里有一个stab作为扩展方法
public static IEnumerable<T> SetPropertyValues<T>(this IEnumerable<T> items, Action<T> action)
{
foreach (var item in items)
{
action(item);
yield return item;
}
}
使用 private class Foo
{
public string Bar { get; set; }
}
[TestMethod]
public void SetPropertyValuesForMiscTests()
{
var foos = new[] { new Foo { Bar = "hi" }, new Foo { Bar = "hello" } };
var newList = foos.SetPropertyValues(f => f.Bar = "bye");
Assert.AreEqual("bye", newList.ElementAt(0).Bar);
Assert.AreEqual("bye", newList.ElementAt(1).Bar);
}
我测试了它,它工作得很好。
是的,你可以这样做。改编自这个答案。
imagesToUnlock.Select(i => {i.IsLocked = false; return i;}).ToList();
编辑:很多人说这是不好的做法。我同意dasblinkenlight的观点。探索LINQ和c#的极限是我们作为程序员的责任。将对象类型从DTO更改为视图模型或域对象并不是不合理的,我知道这不是最好的,但是如果封装并注释,那么使用select来完成此操作并不是世界末日。但是请注意Eric解释的最佳实践。