如何确保此私有只读数组实际上是私有和只读?

时间:2011-01-04 17:50:45

标签: c# readonly

我正在试图弄清楚我是如何成功更改“只读”数组的。下面的代码运行成功,但我很困惑为什么私有/只读数组的解除引用是合法的,如下所示:

namespace ConsoleApplication1
{
  class Program
  {
    static void Main(string[] args)
    {
      MyClass myClass = new MyClass();
      myClass.Time[5] = 5; // Why is this legal? How can I make it illegal?
    }
  }

  public class MyClass
  {
    private readonly uint[] time;
    public IList<uint> Time
    {
      get { return time; }
    }

    public MyClass()
    {
      time = new uint[7];
    }
  }
}

正如我在上面提到的,由于公共IList Time没有设置器,我希望Time [5]是非法的。

如何更改MyClass以确保执行myClass.Time[5] 合法?

注意:我已经澄清了这个问题的意图,我一开始并不清楚是否打算制作这个ILLEGAL。我想先了解为什么它的合法性。

3 个答案:

答案 0 :(得分:5)

  

如上所述,我希望如此   由于时间[5]是非法的   公共IList时间没有   有一个二传手。

缺少setter意味着您无法将NEW ARRAY分配给属性的支持字段,但这并不意味着您无法更改支持字段指向的CURRENT数组引用。

  

此外,我该如何创建   构造函数中的数组是   只读和不可改变的外部   这堂课?

您可以按照MSDN在声明阶段或类的构造函数中设置只读字段。

至于如何解决这个问题,以下MSDN article讨论了这个确切的问题以及解决问题的方法。我不确定您的要求是什么,但我建议您尝试使用ReadOnlyCollectionBase实现自定义集合,然后传递它,或者您可以使用ReadOnlyCollection<T>。 ReadOnlyCollectionBase的链接提供了一个实现示例。

答案 1 :(得分:2)

readonly表示字段本身无法更改(也就是说,你不能在构造函数之外说“this.time = new uint [10]”。数组是可变对象,因此无论您在何处引用数组,该引用的拥有者都可以更改存储在该数组中的值。

readonly字段只能在构造函数中写入(这包括字段初始值设定项)

有两种选择:

  • 在Time属性中执行数组的浅表副本,因此调用者无法修改数组副本
  • 使用ReadOnlyCollection来阻止所有修改

答案 2 :(得分:0)

时间属性没有设置,所以你将无法做到这样的事情:

static void Main(string[] args)
{
  MyClass myClass = new MyClass();
  myClass.Time = new List<uint>();
}

但您可以使用索引器,因此Time [5]是合法的。

  

此外,如何在构造函数中创建一个只读且在此类之外不可更改的数组?

只读字段只能在构造函数中初始化。声明后的初始化与构造函数中的初始化相同。