用防御性副本交换集合
这是我在 Effective C# 中看到的一个示例 book:
private BindingList<PayrollData> data;
public IBindingList MyCollection
{
get { return data; }
}
public void UpdateData()
{
// Unreliable operation might fail:
var temp = UnreliableOperation();
// This operation will only happen if
// UnreliableOperation does not throw an
// exception.
data = temp;
}
作者说这适用于值类型,而不适用于引用类型。 我不明白他的意思。
我想我现在明白了:集合是一种引用类型。 “数据字段”的使用者不会记得他们持有堆上旧存储的副本。 如果“数据”是值类型 - 消费者(使用数据的其他代码)将记住他们持有数据的深层副本,并在需要更新时再次请求它。
正确的 ?
This is an example I have seen in the Effective C# book:
private BindingList<PayrollData> data;
public IBindingList MyCollection
{
get { return data; }
}
public void UpdateData()
{
// Unreliable operation might fail:
var temp = UnreliableOperation();
// This operation will only happen if
// UnreliableOperation does not throw an
// exception.
data = temp;
}
The author says this will work for value type and not for reference type.
I couldn't understand what he meant.
I think I now understand: a collection is a ref type. consumers of "data field" won't remeber they a re holding a copy to the old storage on the heap.
if "data" was value type - the consumers (other code that uses data) will remeber they are holding a deep copy of data and will ask for it again when need to update.
right ?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
该集合是引用类型,因此其他持有该集合的代码将看到旧数据。
两种可能的解决方案:
使用 data.Clear() 代替 data = temp; data.AddRange(temp) 这将更改数据字段的内容。
或者最好删除 MyCollection 属性并让类实现 IEnumerable。这导致更好的封装。
The collection is a reference type, so other holding code onto that will see the old data.
Two possible solutions:
Instead of data = temp use data.Clear(); data.AddRange(temp) which will change the contents of the data field.
Or better delete the MyCollection property and make class implement IEnumerable. This results in much better encapsulation.