是否可以使用 LINQ 执行基于集合的属性分配?
Posted
技术标签:
【中文标题】是否可以使用 LINQ 执行基于集合的属性分配?【英文标题】:Is it possible to perform set based property assignments with LINQ? 【发布时间】:2010-10-29 04:16:29 【问题描述】:我正在尝试测试 LINQ 到底能走多远。我想要实现的是使用单个表达式而不是 for 循环对对象列表进行属性分配。我想获取 listA 中的所有项目并更新 IsMatched
属性,但只有在 listB 中有相应项目的地方(这是不同的类型),这可能吗?
示例代码:
public struct A public int x; public bool IsMatched;
public struct B public int x;
static void Main(string[] args)
List<A> listA = new List<A>();
List<B> listb = new List<B>();
listA.Add(new A() x=1);
listA.Add(new A() x=2);
listA.Add(new A() x=3);
listb.Add(new B() x=2);
listb.Add(new B() x=3);
listA = listA.SelectMany(fb => listb, (fb, j) => new a=fb, b=j)
.Where (anon => anon.b.x == anon.a.x).Select(anon => new A() x=anon.a.x, IsMatched=true)
.ToList(); // this does not do what I want.
我尝试过使用 SelectMany,但这只会返回匹配的项目,或者我不想要的笛卡尔积。
【问题讨论】:
关于副作用的问题,请参阅blogs.msdn.com/b/ericlippert/archive/2009/05/18/… 【参考方案1】:LINQ 并非旨在引起副作用。在这种情况下,请修改集合中的项目。只需创建查询以选择要修改的项目,然后根据需要循环修改它们的项目。
var query = from a in listA
join b in listB on a.x equals b.x
select a;
foreach (var a in query)
a.IsMatched = true;
但是,您可以作弊并制定一个 lambda 来引起副作用。然后将其用作聚合方法。但是,您不应该在实践中这样做。
(from a in listA
join b in listB on a.x equals b.x
let modify = new Func<A,A>(m => m.IsMatched = true; return m; )
select modify(a)).ToArray();
【讨论】:
@Jeff M - 谢谢 - 显然可以在匿名方法检查 this 内完成分配,自己阅读即可。这至少让我成功了一半。 @Jeff M - 对不起,我下次需要更仔细地阅读;)。为什么这样做被认为是不好的做法? @James:如第一部分所述,;) LINQ 的设计并不是为了产生副作用,只是对数据集进行操作。 @Jeff M - 这并不能真正解释为什么这是一个不好的做法,因为它可以毫不费力地完成。 @James:没有什么能阻止你,并不意味着你应该这样做。我不确定我能否充分解释原因。也许Eric Lippert's 文章解释了为什么没有ForEach()
扩展方法(这实际上就是我们在这里所做的)可以解释得足够多。以上是关于是否可以使用 LINQ 执行基于集合的属性分配?的主要内容,如果未能解决你的问题,请参考以下文章
C# LINQ 与两个不同数据集上的条件 where 子句连接