3

我有这个示例代码。我想要做的是使“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();

我真的希望“访问 1”失败,而“访问 2”是可以设置值的唯一方法。在此先感谢您的帮助。

4

2 回答 2

10

√ 务必使用 ReadOnlyCollection(ReadOnlyCollection 的子类),或者在极少数情况下使用 IEnumerable 作为属性或表示只读集合的​​返回值。

这篇文章的引述。

你应该有这样的东西:

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

public ReadOnlyCollection<int> Nums
{
    get
    {
        return _nums.AsReadOnly();
    }
}
于 2015-03-18T17:20:44.873 回答
2

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

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

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

一种更简洁的方法是使用一个名为类似的方法GetNumsAsArray,每次调用它都会返回一个新数组;GetNumsAsList在某些情况下,根据呼叫者对数字的处理方式,使用变体也可能会有所帮助。有些方法只适用于数组,有些只适用于列表,所以如果只提供上述之一,一些调用者将不得不调用它,然后将返回的对象转换为所需的类型。

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

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

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

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

于 2015-03-18T17:37:35.430 回答