属性不应返回数组
本文关键字:数组 返回 属性 | 更新日期: 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;
}
}
}