为什么使用只读 IEnumerable
本文关键字:IEnumerable 只读 为什么 | 更新日期: 2023-09-27 18:22:16
为什么要声明IEnumerable<T>
readonly
?
从这篇关于 async & await 的文章中,我们有以下代码。
class OrderHandler
{
private readonly IEnumerable<Order> _orders;
public OrderHandler()
{
// Set orders.
}
public IEnumerable<Order> GetAllOrders()
{
return _orders;
}
}
IEnumerable<T>
是不可变的。这与readonly
关键字有何不同?
此处的 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 的答案。
延伸阅读
- 只读(C# 参考(
此外,如果它将_orders
定义为不可变,则会添加该事件,这使得不可变仅引用自身,而不引用该集合的内容。我仍然可以在该枚举中更改对象。
因此,从 C# 5.0 开始,我们将得到:
.NET Framework 中的不可变集合
引用文章:
不可变集合是保证它们永远不会的集合 更改其内容并完全线程安全
正如其他人所指出的,一旦对象的构造函数完成,readonly
限定符使存储在类对象的类类型字段中的引用不可变,但对引用可能引用的任何对象都没有这种影响。 没有合理的方法可以使限定符以这种方式影响引用所引用的对象,因为引用的其他副本可能存储在没有此类限定符的字段中。
但是,这并不意味着 readonly
关键字不能有效地应用于可变对象。 假设有一个类Foo
,它有一个包含IEnumerable<KeyValuePair<int,string>>
的字段stuff
,并且希望它公开一个类型的属性Keys
,该类型实现包含stuff
中每个项目的键部分的IEnumerable<int>
。 如果stuff
是只读字段,则Keys
返回的包装对象可以保存对stuff
的引用,并具有对集合的任何更改的"实时视图"。 但是,如果stuff
不是只读字段,则包装对象必须具有对调用 Keys
属性的Foo
的引用,如果它想要确保它始终表现为实时视图。