2014-06-21 62 views
0

我有一个名为ACTIVITY的类。这个类包含一个圈数列表,每个圈都有一个TRACPOINTS集合。LINQ Select Many - 修改展平集合

ACTIVITY --many - > LAPS --- many - > TRACPOINTS。

每当我记录TRACPOINTS集合时,我都会得到所有TRACPOINTS的列表。但是,当我修改那些当然原件不会被修改,因为它是一个副本。

有没有什么办法可以改变Tracpoints列表中每一圈的变化?

+3

为什么? Tracpoint是'struct'吗? –

+2

你可以把一些代码,请 –

+3

_“当然,原件不会被修改,因为它是一个副本”_不一定是,但我们不能确定,直到我们看到代码在哪里你扁平化集合。 –

回答

1

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

只要将结构变量或字段的值赋给其他变量或字段,就会复制其内容。将它作为方法参数传递或从方法返回它同样适用,它的值将被复制。这是价值语义学[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,而不是在你的结构中有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为类似的SelectMany,你可能不关心结构和类这么多之间的性能差异...

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