LINQ选择多个 - 修改展平的集合

时间:2014-06-21 23:26:46

标签: c# linq lambda

我有一个名为ACTIVITY的课程。该类包含一个Laps列表,每个Lap都有一个TRACPOINTS集合。

ACTIVITY - 很多 - > LAPS ---很多 - > TRACPOINTS。

每当我查看TRACPOINTS集合时,我都会获得所有TRACPOINTS的列表。但是当我修改那些原件时,原件不会被修改,因为它是副本。

有没有什么方法可以改变我在每个圈子的Tracpoints列表中对变平的tracpoints做出的改变?

1 个答案:

答案 0 :(得分:1)

只要TRACPOINT是一个结构,就不可能以任何合理的方式。

每当将struct variable或field的值赋给另一个变量或字段时,都会复制其内容。将它作为方法参数传递或从方法返回它同样适用,它的值被复制。这是价值语义[1]。将此与像int这样的原子类型进行比较,它们也具有值语义。您可能希望以下代码打印2而不是3。

static function Change(int j) { j = 3; }
static void Main(string[] args) { 
   int i = 2;
   Change(i);
   System.Console.WriteLine(i);
}

如果执行SelectMany,集合中的每个值可能都会分配给某个临时局部变量,然后从迭代器(SelectMany)返回,因此它会被复制,实际上可能会在从迭代器出来之前复制很多次。所以你要更新的是结构的副本。与示例中一样,您不是更改变量i,而是将其副本存储在变量j中。

这就是结构应该是不可变的原因。它们应该只有getter,而不是在你的struct中使用getter和setter属性。要更改结构的属性值,可以实现复制整个原始结构的方法,更改所需属性的值并返回新的结构实例。事实上,它的副本将被退回。例如:

struct S {
   int f;
   public int F { get { return this.f; } }
   public S SetF(int newVal) {
      var s = new S();
      s.f = newVal;
      return s;
   }
}

var x = new S();
x = x.SetF(30);

也就是说,用指针和不安全的C#实现你想要的东西是可能的,但是相信我,将结构更改为类会更容易,因此它们具有引用语义而不是值语义,或者保持他们结构,但让他们不变,不使用Linq,但旧学校循环。如果你想在这样的场景中使用Linq这样的东西,你可能不关心结构和类之间的性能差异......

[1] http://msdn.microsoft.com/en-us/library/aa664472(v=vs.71).aspx