是的,我知道这个问题之前已经讨论过很多次了,我阅读了所有关于这个问题的帖子和评论,但似乎还是不明白。
MSDN 提供的解决此违规的选项之一是返回一个集合(或由集合实现的接口(interface)>) 访问该属性时,无论多么明显,它都不能解决问题,因为大多数集合不是不可变的,也可以更改。
我在这个问题的答案和评论中看到的另一种可能性是用 ReadOnlyCollection
封装数组并返回它或它的基接口(interface)(如 IReadOnlyCollection
),但我不明白这是如何解决性能问题的。
如果在任何时候引用该属性,它需要为封装数组的新 ReadOnlyCollection
分配内存,那么有什么区别(在性能方面问题,而不是编辑数组/集合)而不是简单地返回原始数组的副本?
此外,ReadOnlyCollection 只有一个带有 IList
参数的构造函数,因此需要在创建数组之前用列表包装数组。
如果我有意在我的类中使用数组(而不是作为不可变集合),当我为 ReadOnlyCollection
分配新内存并用它封装我的数组而不是返回时,性能会更好吗数组的副本?
请澄清这一点。
最佳答案
If at any time the property is referenced it needs to allocate memory for a new ReadOnlyCollection that encapsulates the array, so what is the difference (in a manner of performance issues, not editing the array/collection) than simply returning a copy of the original array?
A 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
的工作量property 必须做 - 它必须获取所有百万条目的副本。考虑 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
属性根本不涉及任何分配 - 如果所有调用者看到相同的包装器并不重要,因为他们不能改变它。
关于c# - 属性不应返回数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34065619/