我有以下通用界面:
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
对象一起使用。有没有办法做到这一点?
答案 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)
虽然很难说没有看到你如何使用TContainer
和TValue
(输入或输出?)但是,您是否尝试使用out
关键字作为泛型类型参数?有关详细信息,请查看Covariance and Contravariance
public interface IContainer<out T>
public interface IGroupOfContainers<out TContainer, TValue>
where TContainer : IContainer<TValue>