使用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更改list's属性

这里的其他解决方案感觉很脏,因为它们通过使用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解释的最佳实践。