通用接口中的通用接口参数

时间:2014-08-24 10:21:05

标签: c# .net generics interface

我有以下通用界面:

public interface IContainer<T>

以及充当这些通用接口的容器的通用接口:

public interface IGroupOfContainers<TContainer, TValue>
    where TContainer : IContainer<TValue>

现在我可以定义一些类:

public class SomeContainer<T> : IContainer<T>
...

public class OtherContainer<T> : IContainer<T>
...

public class SomeGroupOfContainers<TContainer, TValue>
    : IGroupOfContainers<TContainer, TValue>
    where TContainer : IContainer<TValue>
...

public class OtherGroupOfContainers<TContainer, TValue>
    : IGroupOfContainers<TContainer, TValue>
    where TContainer : IContainer<TValue>
...

现在我希望IntGroupManager能够使用符合IGroupOfContainers<IContainer<int>, int>接口的任何对象:

public class IntGroupManager
{
    public IGroupOfContainers<IContainer<int>, int> IntGroup { get; set; }
    ...
}

但是当我尝试时:

var manager= new IntGroupManager();
manager.IntGroup = new GroupOfContainers<Container<int>, int>
    as IGroupOfContainers<IContainer<int>, int>;

我得到“可疑演员:没有从GroupOfContainers<Container<int>, int>IGroupOfContainers<IContainer<int>, int>警告继承的类型,当我尝试运行代码时,{由于演员失败,{1}}设置为manager.IntGroup

如果我将null属性的类型签名更改为

IntGroup

(将public IGroupOfContainers<Container<int>, int> IntGroup { get; set; } 更改为具体类IContainer),代码正确执行。但是,我无法使用Container类型IntGroupManager来实例化IntGroup的实例,例如GroupOfContainers<OtherContainer<int>, int>,因为OtherContainer不是从{{1}派生的}}

我可以将通用参数引入Container的定义,也许将其重写为

IntGroupManager

但是,这会将public class IntGroupManager<TContainer> where TContainer : IContainer<int> 的任何实例绑定到特定类型的IntGroupManager;我无法做到

IContainer

所以我失去了一些灵活性。

如何正确地将var manager = new IntGroupManager<Container<int>>(); // Set manager.IntGroup and do some things with it // This is okay manager.IntGroup = new GroupOfContainers<Container<int>, int>(); // manager executes some code involving IntGroup and manipulates its internal state // Set manager.IntGroup to something else and do things with it // This is not okay, since OtherContainer<int> is not derived from Container<int> manager.IntGroup = new GroupOfContainers<OtherContainer<int>, int>(); 属性定义为符合IntGroup的任何类型?我希望能够将IGroupOfContainers<IContainer<int>, int>的同一个实例与符合IntGroupManager的任何IntGroup对象一起使用。有没有办法做到这一点?

2 个答案:

答案 0 :(得分:2)

这是穆罕默德答案评论中对你问题的回答(对不起,评论太久了):

  

如果它是输入或输出,而不是两者,[协方差]将是解决方案,对吧?即使IGroupOfContainers定义了使用TContainer作为输入和输出的函数,有没有办法做到这一点?

让我们继续您的示例,并假设以下语句有效:

var g = new GroupOfContainers<Container<int>, int>
    as IGroupOfContainers<IContainer<int>, int>;

我们假设IGroupOfContainers<TContainer, TValue>有方法AddContainer(TContainer)

g.AddContainer(new OtherContainer<int>());

这会编译,因为OtherContainer<int>IContainer<int>

但是,您刚刚向一组OtherContainer添加了Container!这就是为什么你不能做你想做的事情,除非你阻止IGroupOfContainers接受TContainer输入。

答案 1 :(得分:1)

虽然很难说没有看到你如何使用TContainerTValue(输入或输出?)但是,您是否尝试使用out关键字作为泛型类型参数?有关详细信息,请查看Covariance and Contravariance

public interface IContainer<out T>

public interface IGroupOfContainers<out TContainer, TValue>
    where TContainer : IContainer<TValue>