我有2个客户端使用的公共接口
public interface IASet<T> where T : IItem {
HashSet<T> Collection { get; set; }
}
public interface IItem {
string Name { get; set; }
}
这个想法是客户端通过这个对象访问数据:
IASet<IItem> aset = GetIt();
foreach(IItem i in aset.Collection)
Console.WriteLine(i.Name);
具体实施如下:
private class ASet : IASet<OneItem>{
public HashSet<OneItem> Collection { get; set; }
}
private class OneItem : IItem{
public string Name { get; set; }
}
最终生成对象的函数:
public static IASet<IItem> GetIt()
{
ASet a = new ASet();
a.Collection = new HashSet<OneItem>();
a.Collection.Add(new OneItem() { Name = "one" });
a.Collection.Add(new OneItem() { Name = "two" });
//for test :
foreach (IItem i in a.Collection)
{
Console.WriteLine(i.Name);
}
/*Error 1 Cannot implicitly convert type 'ConsoleApplication2.Program.ASet'
* to 'ConsoleApplication2.IASet<ConsoleApplication2.IItem>'. An explicit
* conversion exists (are you missing a cast?)
*/
//return a;
/*Unable to cast object of type 'ASet' to type
* 'ConsoleApplication2.IASet`1[ConsoleApplication2.IItem]'.
*/
return (IASet<IItem>)a;
}
因为我的真实代码并不像这个简单,所以我无法将ASet : IASet<OneItem>
更改为ASet<T> : IASet<T>
请您解释一下为什么我不能这样做,以及一些纠正问题的建议?
由于
答案 0 :(得分:1)
我认为你应该看看我对这个问题的回答,它解释了你的案例Interface with generic object of the interface type
顺便提一句,我建议你改变你的GetIt功能:
public static IASet<T> GetIt<T>()
where T : IItem
{
ASet a = new ASet();
a.Collection = new HashSet<OneItem>();
a.Collection.Add(new OneItem() { Name = "one" });
a.Collection.Add(new OneItem() { Name = "two" });
//for test :
foreach (var i in a.Collection)
{
Console.WriteLine(i.Name);
}
/*Error 1 Cannot implicitly convert type 'ConsoleApplication2.Program.ASet'
* to 'ConsoleApplication2.IASet<ConsoleApplication2.IItem>'. An explicit
* conversion exists (are you missing a cast?)
*/
//return a;
/*Unable to cast object of type 'ASet' to type
* 'ConsoleApplication2.IASet`1[ConsoleApplication2.IItem]'.
*/
return (IASet<T>)a;
}
然后你需要这样称呼它:
IASet<OneItem> aset = GetIt<OneItem>();
foreach (IItem i in aset.Collection)
Console.WriteLine(i.Name);
如果您需要更多详细信息,则需要更多地解释您的要求。
答案 1 :(得分:0)
这里的问题是您返回ASet
的实例,但返回类型为IASet<IItem>
。 ASet
类型实际上实现了接口IASet<OneItem>
。即使IASet<IItem>
实现OneItem
,此接口也无法转换为IITem
。
当IASet
上的类型参数标有out
(即IASet<out T>
)时,允许此类型的转化。这会将类型参数标识为协变,并允许此类转换。
不幸的是,这在您的方案中是不可能的。考虑out T
的最简单方法是T
仅出现在API的输出位置。在这种情况下,T
中使用了HashSet<T>
。因此,T
出现在输入和输出位置,因此T
无法标记为out
。