包含给定接口/类的任何<t>的“强类型”通用集合

时间:2019-03-19 18:13:46

标签: c# generic-collections

是否可以声明一个通用集合,以仅容纳使用任何<T>实现通用接口的对象?

我的问题归结为:如果我想/必须存储实现通用接口的对象,那么与使用非通用集合或{{1}的通用)相比,有没有更好的方法来表达这一事实。

示例:

<Object>

这有可能吗?任何建议都将受到高度赞赏!

更新:新的,更详细的代码来阐明问题。

以下建议将通用接口基于非通用接口。但是结果是,通用接口的所有实现类都必须实现非通用方法,属性等。-还是可以解决吗?

感谢您的输入!

2 个答案:

答案 0 :(得分:3)

  

是否可以声明一个通用集合以仅保存实现用 any T实例化的通用接口的对象?

简短回答:否。

更长的答案:不,因为那没有用。

让我们考虑一个简单的通用接口:

interface I<T> { T Get(); }

和一堆实现它的对象:

class Lion : I<Lion> 
{
  public Lion Get() => this;
}
class TaxPolicyFactory : I<TaxPolicy>
{
  public TaxPolicy Get() => new TaxPolicy();
}
class Door: I<Doorknob>
{
  public Doorknob Get() => this.doorknob;
  ...
}

好的,现在假设您有一个List<I<ANYTHING>>,如您所愿:

var list = new List<I<???>> { new TaxPolicyFactory(), new Lion(), new Door() };

您有一个包含税收政策工厂,狮子和门的清单。这些类型没有什么共同点。您无法对每个对象执行任何操作。即使您可以分别对它们调用Get,您也会有一个包含税收政策,狮子和门把手的序列,您将如何处理?

没有,就是那样。约束“对于任何I<T>的实现接口T”在C#中根本不是有用的约束,因此无法表达它。

听起来您遇到了“ XY”问题。在脑海中有一个不好的解决方案时,这是一个问题,现在您正在询问有关您的不好的解决方案的问题。 向我们询问有关您遇到的实际问题的信息,而不是关于解决方案的坏主意。真正的问题是什么?


更新:有了问题中的新信息,现在更加清楚了。您想要的功能称为通用接口协方差,这是我最喜欢的C#4功能。

如果您将界面定义更新为

interface ISyncInterface<out T> { ... }

然后,您可以在需要ISyncInterface<String>的情况下使用ISyncInterface<Object>。例如,您可以将ISyncInterface<Giraffe>放入List<ISyncInterface<Animal>>或其他任何内容中。

但是,您需要确保接口定义仅在协变有效位置使用T 。接口如所述有效,但是例如,如果您想向接口添加方法void M(T t);,它将不再协变有效。 “ out”是一个助记符,告诉您T只能用作方法的输出。由于IEnumerable<T>也是协变有效的,所以很好; T中没有IEnumerable<T>输入

此外,差异仅适用于通用接口和委托,并且不同类型必须是引用类型。您不能将ISyncInterface<int>放入List<ISyncInterface<Object>>中,因为int不是引用类型。

关于SO的协方差和协方差的帖子很多。您还应该阅读Microsoft文档。这可能是一个令人困惑的功能。如果您对我们设计和实现功能的历史细节感兴趣,请参阅我的博客。

答案 1 :(得分:0)

也许您可以尝试以下方法:

  public interface MyInterface
  {//methods common to all types
    void FirstMethod();
  }
  public interface MyInterface<T> : MyInterface
  {//methods specific to a type
    void FirstMethod(T parameter);
  }
  public class MyClassThatHandlesAllInterfaces
  {
    private List<MyInterface> _allInterfacesT; //first interface in the chain
    public void AddInterface<T>(MyInterface<T> ifToAdd)
    {
      _allInterfacesT.Add(ifToAdd); // <- this is what I'd like to do
    }
  }

我经常使用这种模式。因为我不知道有关您方案的所有详细信息,所以它可能不适合您。

但这可能会帮助其他人搜索Google。