我有对象数组(假设类名是Snap)Snap。
有没有办法保存变量直接引用单元格中的对象,而不是单元格? 因为,当我这样做时:
Snap[] goo = new Snap[3];
// here we add some objects to this array
Snap foo = (Snap)goo[1];
所以现在,如果我改变foo,那么我也会改变goo [1]。好。但现在我将在goo上做一些排列:
first i had: 0 1 2
after permutation: 1 0 2
foo仍然是goo [1]但不是这个对象!这个对象现在在goo [0]! 那么,如何直接“捕捉”这个对象,而不是单元格! 有什么想法吗?
答案 0 :(得分:6)
foo
的值是对象的直接引用......但goo[1]
也是如此。它们引用相同的对象,因此如果你改变了对象(不管你做了什么),那么这些改变都将通过两个引用来看到。
请注意,通过 foo
更改值实际上并未更改foo
的值。我喜欢从房屋(作为对象),街道地址(作为参考)和纸张(作为变量)的角度来考虑它。假设我把我的地址写在两张纸上,然后给你一个,给别人一个(弗雷德)。然后你把我的房子涂成红色,然后弗雷德来参观(通过阅读写在纸上的地址)。你改变了我家的颜色 - 但你根本没有改变弗雷德的那张纸。
如果你想避免这种别名,你应该考虑使你的类型不可变,并提供创建新对象的方法,这些对象就像旧对象一样,除了一些特定的变化 - 比如String
那样做,例如
答案 1 :(得分:2)
没有直接(安全)方法来创建对.NET数组中元素的“地址”之类的引用。但是,您可以使用委托而不是引用,并编写类似:
的内容Snap[] goo = new Snap[3];
Func<Snap> foo = () => (Snap)goo[1];
现在,foo
是一个可以评估的函数,用于获取索引处的对象。您可以像这样使用它:
foo().SomeSnapProperty = 10;
如果您现在对goo
个对象进行排列,然后再次运行上述语句,它将在索引1处为您提供新对象(因此您将修改另一个Snap
)
答案 2 :(得分:1)
你错过了这一点。
Snap[] goo = new Snap[3];
将goo
声明为对Snap
实例的引用数组。也就是说,goo
的每个元素都是引用,而不是Snap
的实例。
Snap foo = goo[1];
现在,您已将foo
声明为对Snap
实例的引用,它恰好指的是与Snap
相同的goo[1]
实例
所以现在,如果我改变foo,那么我也会改变goo [1]。
更准确地说,如果您更改foo
引用的实例,它也会更改goo[1]
引用的实例(因为它们都指向同一个实例)。
但现在我将在goo上做一些排列
这意味着您要更改每个元素引用的Snap
实例。由于您从未告诉foo
也更改它所引用的Snap
实例,当然它仍然引用它最初引用的相同实例。