是否可以使用 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 子句连接

如何将相同的 var 类型变量分配给不同的 linq to sql 结果集?

是否应该使用 Linq? [关闭]

LINQ 与传统基于集合的方法之间的优缺点

LINQ 和内存分配

linq 问题:查询嵌套集合