为什么要声明IEnumerable<T>
readonly
?
从这个article on async & await我们得到以下代码。
class OrderHandler
{
private readonly IEnumerable<Order> _orders;
public OrderHandler()
{
// Set orders.
}
public IEnumerable<Order> GetAllOrders()
{
return _orders;
}
}
IEnumerable<T>
是不可变的。这与readonly
关键字有什么不同?
答案 0 :(得分:5)
此处的readonly
关键字适用于字段_orders
。它只是意味着在对象的生命周期内不能为字段分配不同的值。例如,这是不可能的:
class OrderHandler
{
private readonly IEnumerable<Order> _orders;
public OrderHandler()
{
// Set orders.
}
void SomeMethod()
{
_orders = new Order[0];
}
}
您将收到此编译器错误:
无法分配
readonly
字段(构造函数或变量初始值设定项除外)
此不使该集合成为只读。例如,你仍然可以这样做:
class OrderHandler
{
public readonly IEnumerable<Order> Orders;
public OrderHandler()
{
Orders = new List<Order>();
}
}
((List<Order>)OrderHandler.Orders).Add(new Order());
这可能违反了班级的线程安全性。有关不可变集合的信息,请参阅Tigran's answer。
进一步阅读
答案 1 :(得分:4)
另外如果将_orders
定义为不可变,则会添加该事件,这使得immutable只引用自身,而不是该集合的内容。我仍然可以在枚举中更改对象。
因此从C#5.0开始,我们将得到:
Immutable Collections in .NET Framework
引用文章:
不可变集合是保证它们永远不会的集合 改变他们的内容并完全线程安全
答案 2 :(得分:0)
正如其他人所说,readonly
限定符使得引用存储在类对象的类类型字段中,一旦该对象的构造函数完成,就会不可变,但是没有这样的效果在引用可能引用的任何对象上。没有合理的方法,限定符可以通过这种方式影响引用引用的对象,因为引用的其他副本可以存储在没有这种限定符的字段中。
然而,这并不意味着readonly
关键字无法有效地应用于可变对象。假设有一个类Foo
,其字段stuff
持有IEnumerable<KeyValuePair<int,string>>
,并且有人希望它公开实现Keys
的类型的属性IEnumerable<int>
包含stuff
中每个项目的关键部分。如果stuff
保持只读字段,则Keys
返回的包装器对象可以保存对stuff
的引用,并具有对该集合进行任何更改的“实时视图”。但是,如果stuff
不是只读字段,则包装器对象必须具有Foo
的引用,如果要确保调用Keys
属性它总是表现为实时视图。