在 C# 中创建只读列表

Make a list readonly in c#

我有这个示例代码。我想要做的是使 "Nums" 值只能使用 "AddNum" 方法写入。

namespace ConsoleApplication1
{
    public class Person
    {
        string myName = "N/A";
        int myAge = 0;
        List<int> _nums = new List<int>();

        public List<int> Nums
        {
            get
            {
                return _nums;
            }
        }

        public void AddNum(int NumToAdd)
        {

            _nums.Add(NumToAdd);
        }

        public string Name { get; set; }
        public int Age { get; set; }
    }
}

不知何故,我已经尝试了很多关于 AsReadOnly() 和 readonly 关键字的事情,但我似乎无法让它做我想做的事情。

这是我必须访问 属性 的代码示例。

Person p1 = new Person();
p1.Nums.Add(25); //access 1
p1.AddNum(37); //access 2

Console.WriteLine("press any key");
Console.ReadLine();

我真的希望 "access 1" 失败,"access 2" 成为 唯一 可以设置值的方式。在此先感谢您的帮助。

√ DO use ReadOnlyCollection, a subclass of ReadOnlyCollection, or in rare cases IEnumerable for properties or return values representing read-only collections.

引自this article

你应该有这样的东西:

List<int> _nums = new List<int>();

public ReadOnlyCollection<int> Nums
{
    get
    {
        return _nums.AsReadOnly();
    }
}

一般来说,集合类型的属性很差,因为即使集合被包装在 ReadOnlyCollection 中,本质上也不清楚是什么:

IEnumerable<int> nums = myPerson.Nums;
myPerson.AddNum(23);
foreach(int i in nums) // Should the 23 be included!?
  ...

应该是这个意思。 return从 Nums 中编辑的对象是否是它调用时存在的数字的快照,是实时视图吗?

一种更简洁的方法是使用一个类似于 GetNumsAsArray 的方法,每次调用时 return 都会创建一个新数组;在某些情况下,使用 GetNumsAsList 变体也可能会有所帮助,具体取决于呼叫者希望对号码执行的操作。有些方法只适用于数组,有些只适用于列表,因此如果仅提供上述方法之一,一些调用者将不得不调用它,然后将 returned 对象转换为所需的类型。

如果对性能敏感的调用者将需要大量使用此代码,拥有更通用的方法可能会有所帮助:

int CopyNumsIntoArray(int sourceIndex, int reqCount, ref int[] dest, 
                      int destIndex, CopyCountMode mode);

其中 CopyCountMode 指示代码应执行的操作从 sourceIndex 开始的可用项目数大于或小于 reqCount;该方法应该 return 可用项目的数量,或者如果它违反了调用者规定的期望则抛出异常。一些调用者可能首先创建并传入一个包含 10 个项目的数组,但如果要 returned 的项目超过 10 个,则准备好让该方法用更大的数组替换它;其他人可能期望正好有 23 件物品,并且没有准备好处理任何其他数量的物品。使用参数指定模式将允许一种方法为多种调用者提供服务。

尽管许多集合作者不费心包含任何符合上述模式的方法,但在代码想要处理集合中的少数项目(例如集合中的 1,000 项)的情况下,此类方法可以大大提高效率50,000 个)。在没有此类方法的情况下,希望使用此类范围的代码必须请求整个事物的副本(非常浪费)或单独请求数千个项目(也很浪费)。在同一方法进行多次查询的情况下,允许调用者提供目标数组将提高效率,尤其是如果目标数组大到足以放入大型对象堆时。