3

我有一个类,它定义了一个有效公开私有字段的只读属性,如下所示:

public class Container
{
    private List<int> _myList;

    public List<int> MyList
    {
        get { return _myList;}
    }

    public Container() : base ()
    {
        _myList = new List<int>();
    }

    // some method that need to access _myList
    public SomeMethod(int x)
    {
         _myList.Add(x);
    }
}

现在消费者不可能直接管理我的财产,所以像 aContainer.MyList = new List(); 这样的代码 生成编译时错误。但是,消费者完全可以自由地调用他得到的引用的各种方法,所以这是完全有效的代码

Container c = new Container();  
Console.WriteLine(c.MyList.Count);  
c.MyList.Add(4);  
Console.WriteLine(c.MyList.Count);  

哪种破坏了整个只读概念。

是否有任何健全的解决方法可以让我拥有真正的只读参考属性?

PS我不能只返回列表的副本,因为这样用户会认为他做了所有必要的更改,但是唉......他们会消失的。

4

5 回答 5

5

不要返回对您列表的直接引用。而是返回一个包裹在它周围的 ReadOnlyCollection,或者如果 List<> 返回类型一成不变,则返回列表的副本。他们可以在不影响原件的情况下对副本做任何他们想做的事情。

于 2009-01-14T14:38:57.673 回答
2

引用是"readonly",即实际对象。即你不能用另一个对象替换引用。因此,如果您有一个像这样破坏它的课程:

public class Container
{
    private readonly  List<int> _myList;

    public List<int> MyList
    {
        get { return _myList;}
    }

    public Container() : base ()
    {
        _myList = new List<int>();
    }

    public void BreakReadOnly()
    {
        _myList = new List<int>();
    }
}

…然后它甚至不会编译。这是因为只读字段不能用任何其他对象重新分配。在这种情况下BreakReadOnly将尝试分配一个新列表。

如果你真的想要它的只读集合,那么你可以这样做:

    public ReadOnlyCollection<int> MyList
    {
        get { return _myList.AsReadOnly(); }
    }

希望这可以帮助。

更新:删除了 IEnumerable 的使用。

于 2009-01-14T14:40:26.813 回答
2

你可以像这样返回一个只读集合

    public ReadOnlyCollection<int> MyList
    {
        get { return _myList.AsReadOnly(); }
    }

或返回一个新列表,以便调用者可以在不更改原始列表的情况下更改列表。

    public List<int> MyList
    {
        get { return new List<int>(_myList)}
    }
于 2009-01-14T14:56:36.390 回答
1

看看静态Array.AsReadOnly()方法,您可以使用它来返回一个数组的包装器,以防止它被修改。

于 2009-01-14T14:38:30.123 回答
0

您希望 _myList,这是一个只读的引用类型。好吧,它是只读的,只读概念没有失败。

CLR 以这样一种方式为引用类型实现只读属性,即引用(如果需要,指向对象的指针)是只读的,而引用指向的对象可以修改。

要解决此问题,您需要将对象本身的成员字段设置为只读,因为您无法通过将只读标志附加到对象的引用来使整个对象变为只读。

您可以实现您的不可变泛型集合类,该类的行为方式与 List<> 对象相同,但具有只读成员。

于 2009-01-14T14:54:45.113 回答