1

Why would you declare an IEnumerable<T> readonly?

From the this article on async & await we have the following code.

class OrderHandler
{
    private readonly IEnumerable<Order> _orders;

    public OrderHandler()
    {
        // Set orders.
    }
    public IEnumerable<Order> GetAllOrders()
    {
        return _orders;
    }
}

IEnumerable<T> is immutable. How is this different from the readonly keyword?

4

3 回答 3

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的答案

延伸阅读

于 2013-07-15T08:23:18.770 回答
4

此外,如果该事件定义_orders为不可变,则会添加该事件,这使得不可变仅引用自身,而不是该集合的内容。我仍然可以更改该枚举中的对象。

出于这个原因,从 C# 5.0 开始,我们将得到:

.NET Framework 中的不可变集合

引用文章:

不可变集合是保证它们永远不会更改其内容并且完全线程安全的集合

于 2013-07-15T08:26:47.670 回答
0

正如其他人所指出的那样,一旦该对象的构造函数完成,readonly限定符使存储在类对象的类类型字段中的引用不可变,但对引用可能引用的任何对象都没有这种影响。没有合理的方法可以使限定符以这种方式影响引用所指的对象,因为引用的其他副本可能存在存储在没有此类限定符的字段中。

然而,这并不意味着readonly关键字不能有效地应用于可变对象。假设一个类Foo的字段stuff包含一个IEnumerable<KeyValuePair<int,string>>,并且希望它公开一个类型的属性Keys,该类型实现IEnumerable<int>包含 中每个项目的键部分stuff。如果stuff持有一个只读字段,则返回的包装对象Keys可以持有stuff对集合的任何更改的引用并具有“实时视图”。但是,如果stuff不是只读字段,则包装对象必须具有对调用FooKeys属性的 的引用,以确保它始终表现为实时视图。

于 2013-07-15T20:29:11.153 回答