gpt4 book ai didi

c# - 在 C# 中返回集合时如何处理协方差?

转载 作者:太空狗 更新时间:2023-10-29 17:58:36 25 4
gpt4 key购买 nike

我在返回集合和协方差方面遇到问题,我想知道是否有人有更好的解决方案。

场景是这样的:

我有 2 个版本的实现,我希望将版本实现完全分开(即使它们可能具有相同的逻辑)。在实现中,我想返回一个项目列表,因此在界面中,我会返回一个项目界面列表。但是,在接口(interface)的实际实现中,我想返回项目的具体对象。在代码中,它看起来像这样。

interface IItem
{
// some properties here
}

interface IResult
{
IList<IItem> Items { get; }
}

然后,将有 2 个命名空间,它们具有这些接口(interface)的具体实现。例如,

命名空间版本 1

class Item : IItem

class Result : IResult
{
public List<Item> Items
{
get { // get the list from somewhere }
}

IList<IItem> IResult.Items
{
get
{
// due to covariance, i have to convert it
return this.Items.ToList<IItem>();
}
}
}

同样的东西在命名空间 Version2 下会有另一个实现。

要创建这些对象,将有一个工厂获取版本并根据需要创建适当的具体类型。

如果调用者知道确切的版本并执行以下操作,则代码可以正常工作

Version1.Result result = new Version1.Result();
result.Items.Add(//something);

但是,我希望用户能够做这样的事情。

IResult result = // create from factory
result.Items.Add(//something);

但是,因为它已被转换为另一个列表,所以添加不会执行任何操作,因为该项目不会被添加回原始结果对象。

我可以想到一些解决方案,例如:

  1. 我可以同步这两个列表,但这似乎是额外的工作要做
  2. 返回 IEnumerable 而不是 IList 并添加创建/删除集合的方法
  3. 创建一个采用 TConcrete 和 TInterface 的自定义集合

我理解为什么会发生这种情况(由于类型安全和所有),但我认为没有任何解决方法看起来非常优雅。有没有人有更好的解决方案或建议?

提前致谢!

更新

经过深思熟虑,我认为我可以做到以下几点:

public interface ICustomCollection<TInterface> : ICollection<TInterface>
{
}

public class CustomCollection<TConcrete, TInterface> : ICustomCollection<TInterface> where TConcrete : class, TInterface
{
public void Add(TConcrete item)
{
// do add
}

void ICustomCollection<TInterface>.Add(TInterface item)
{
// validate that item is TConcrete and add to the collection.
// otherwise throw exception indicating that the add is not allowed due to incompatible type
}

// rest of the implementation
}

那我可以拥有

interface IResult
{
ICustomCollection<IItem> Items { get; }
}

then for implementation, I will have

class Result : IResult
{
public CustomCollection<Item, IItem> Items { get; }

ICustomCollection<TItem> IResult.Items
{
get { return this.Items; }
}
}

这样,如果调用者正在访问 Result 类,它将通过已经是 TConcrete 的 CustomCollection.Add(TConcrete item)。如果调用者通过 IResult 接口(interface)访问,它将通过 customCollection.Add(TInterface item) 并进行验证并确保类型实际上是 TConcrete。

我会试一试,看看是否可行。

最佳答案

你面临的问题是因为想要公开一个类型,它说(除其他外)“你可以添加任何 IItem对我来说”,但它实际上会做的是“你只能添加 Item对我来说”。我认为最好的解决方案是实际公开 IList<Item> .使用它的代码必须了解具体的 Item无论如何,如果它应该将它们添加到列表中。

但是如果你真的想这样做,我认为最干净的解决方案是 3.,如果我理解正确的话。它将成为 IList<TConcrete> 的包装器它将执行 IList<TInterface> .如果您尝试将不是 TConcrete 的内容放入其中,它会抛出异常。

关于c# - 在 C# 中返回集合时如何处理协方差?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7379746/

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