属性不应返回数组

本文关键字:数组 返回 属性 | 更新日期: 2023-09-27 18:25:33

是的,我知道这个问题以前已经讨论过很多次了,我阅读了所有关于这个问题的帖子和评论,但似乎仍然无法理解。

MSDN提供的解决此冲突的选项之一是,在访问属性时返回集合(或由实现的接口),但很明显,并不能解决问题,因为大多数集合不是不可变的,也可以更改。

我在这个问题的答案和评论中看到的另一种可能性是用ReadOnlyCollection封装数组,并返回它或它的基本接口(如IReadOnlyCollection),但我不明白这是如何解决性能问题的。

如果在任何时候引用该属性,它都需要为封装数组的新ReadOnlyCollection分配内存,那么(在性能问题方面,不编辑数组/集合)与简单地返回原始数组的副本有什么区别呢?

此外,ReadOnlyCollection只有一个带有IList参数的构造函数,因此在创建数组之前需要用列表包装数组

如果我有意使用类中的数组(而不是作为不可变集合),那么当我为ReadOnlyCollection分配新内存并用它封装数组而不是返回数组的副本时,性能会更好吗?

请澄清这一点。

属性不应返回数组

如果在任何时候引用该属性,它都需要为封装数组的新ReadOnlyCollection分配内存,那么(在性能问题方面,而不是编辑数组/集合)与简单地返回原始数组的副本有什么区别呢?

ReadOnlyCollection<T>包装集合-它不会复制该集合。

考虑:

public class Foo
{
    private readonly int[] array; // Initialized in constructor
    public IReadOnlyList<int> Array => array.ToArray(); // Copy
    public IReadOnlyList<int> Wrapper => new ReadOnlyCollection<int>(array); // Wrap
}

假设您的数组包含一百万个条目。考虑一下Array属性必须做的工作量——它必须复制所有一百万个条目。考虑一下Wrapper属性必须做的工作量——它必须创建一个只包含引用的对象。

此外,如果你不介意额外的内存命中,你可以做一次:

public class Foo
{
    private readonly int[] array; // Initialized in constructor
    private readonly IReadOnlyList<int> Wrapper { get; }
    public Foo(...)
    {
        array = ...;
        Wrapper = new ReadOnlyCollection<int>(array);
    }
}

现在,访问Wrapper属性根本不涉及任何分配-如果所有调用方都看到相同的包装器也没关系,因为他们无法对其进行变异。

您不需要复制数组,只需将其返回为IReadOnlyCollection<T>:

  public class MyClass {
    private int[] myArray = ...
    public IReadOnlyCollection<int> MyArray {
      get {
        return myArray;
      }
    }
  }