gpt4 book ai didi

c# - 当项目最初必须可变时返回不可变集合

转载 作者:太空宇宙 更新时间:2023-11-03 22:23:56 24 4
gpt4 key购买 nike

一般情况的一个例子:

public class Validator
{
// ...
public ReadOnlyCollection<InvalidContainer> ContainersUnderMinimum
{
get { return _containersUnderMinimum.AsReadOnly(); }
}
}

public class InvalidContainer
{
// ...
public int LowestVolume { get; set; }
}

上面的 Validator 类在其构造函数中获取其他项目的集合,然后将无效项目添加到内部列表中。每个容器都有许多子容器(想象一架试管),类(class)想要找到体积最小的。构造函数在未找到项目(管)时添加到列表,并在找到项目时更新现有列表对象。

问题是 Validator 想要返回不可变对象(immutable对象)的只读集合,但对象 (InvalidContainers) 必须在构造后可变,以便可以(本质上)累积值。

重构以使用接口(interface) (IInvalidContainer) 会让人头疼,因为泛型集合无法转换为基类型的集合。

有哪些好的模式或做法可以解决这个问题?

编辑:澄清一下,目的是让属性值(集合)不可变。我知道 ReadOnlyCollection 只强制集合的不变性,而不是集合项的不变性。通常我会让项目不可变,但我不能在这种(和类似的)情况下。但是,我只希望在构造 Validator 类时改变项目。防止调用者进行不明智的转换不是设计目标;目标是避免使用可设置的公共(public)属性来吸引调用者。

编辑:为清楚起见更改了标题。

编辑:这是重构后的版本(基于 LBushkin 和递归的建议):

public IEnumerable<IInvalidContainer> ContainersUnderMinimum
{
get
{
return _containersUnderMinimum.Cast<IInvalidContainer>();
}
}

最佳答案

如果我对你的问题的理解正确,你想返回一个不可变类型的集合,但在内部保留一个可变集合。这样做的典型方法是为您的类型创建一个不可变的基类型(或接口(interface))并返回它。

您可以将项目转换为该类型(一种弱形式的不变性控制),或者您可以创建包装对象并返回它们(一种强类型的控制)。包装器对象的创建成本可能更高 - 但它们会阻止外部代码简单地执行类型转换来绕过不变性。顺便说一句,这是 ReadOnlyCollection<T> 的机制。用于返回不可变集合。

为了克服集合类型对转换支持有限这一事实,您可以使用 LINQ 返回不可变类型的不可变副本:

_containersUnderMinimum.Cast<IInvalidContainer>().ToList().AsReadOnly()

这会创建集合的副本 - 但它可能已经足够好了 - 如果您不需要集合来反射(reflect)运行时的更改。

另外,请注意 ReadOnlyCollection 不要求(或强制执行) 集合元素的不变性。相反,它会阻止接收方添加或删除元素 - 仍然可以更改集合中的现有元素。

关于c# - 当项目最初必须可变时返回不可变集合,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2103636/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com