LINQ选择许多-修改扁平集合
本文关键字:集合 修改 选择 许多 LINQ | 更新日期: 2023-09-27 18:09:36
我有一个名为ACTIVITY的类。该类包含一个圈的列表,每个圈都有一个tracpoint的集合。
活动————>圈——许多——> TRACPOINTS。
每当我平放TRACPOINTS集合时,我都会得到所有TRACPOINTS的列表。但是当我修改这些内容的时候,原件当然不会被修改,因为它是副本。
是否有任何方法,无论我对平面化跟踪点做了什么改变,在每一圈的跟踪点列表中都会发生变化?
只要TRACPOINT是一个结构体,就不可能以任何合理的方式。
当你将struct变量或字段的值赋给另一个变量或字段时,它的内容将被复制。将其作为方法参数传递或从方法返回时也是如此,它的值将被复制。这是值语义[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和setter的属性,而应该只有getter。要改变结构体的属性值,可以实现复制整个原始结构体的方法,改变所需属性的值并返回新的结构体实例。事实上,它的副本会被归还。例子:
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来做一些像SelectMany这样的事情,你可能不太关心结构和类之间的性能差异…
[1] http://msdn.microsoft.com/en-us/library/aa664472 (v = vs.71) . aspx