【发布时间】:2012-02-02 16:04:57
【问题描述】:
我一直忙于 C# 4.0 泛型,现在我基本上想做这样的事情:
public abstract class GenericTree<T> : Tree
where T : Fruit
{
public Tree(IFruitCollection<T> fruits)
: base(fruits) { }
}
基本的 Tree 类如下所示:
public abstract class Tree
{
private IFruitCollection<Fruit> fruits;
public IFruitCollection<Fruit> GetFruits
{
get { return fruits; }
}
public Tree(IFruitCollection<Fruit> fruits)
{
this.fruits = fruits;
}
}
这是我的第一个问题。 GenericTree 的构造函数不能将泛型集合转换为水果集合。我还有一个 GenericTree 的实现:
public class AppleTree : GenericTree<Apple>
{
public AppleTree()
: base(new FruitCollection<Apple>) { }
}
这是我的第二个问题。当我使用 myAppleTree.GetFruits.Add(...) 将水果添加到 AppleTree 实例时,我不仅限于使用苹果。我可以添加各种水果。我不想要这个。
我试图通过将它添加到 GenericTree 来解决这个问题:
new public IFruitCollection<T> GetFruits
{
get { return base.GetFruits as IFruitCollection<T>; }
}
但这也是不可能的。它总是以某种方式返回null。当我的第一个问题解决后,这可能会得到解决。
IFruitCollection 界面如下所示:
public interface IFruitCollection<T> : ICollection<T>
where T : Fruit { ... }
FruitCollection 类是 Collection 类的简单实现。 哦,当然,Apple 类扩展了 Fruit 类。
解决方案是使 IFruitCollection 接口同时兼容协变和逆变。但是我该如何实现呢? "in" 或 "out" 参数关键字是不可能的,因为 ICollection 接口不允许这样做。
非常感谢您的帮助!
【问题讨论】:
-
请注意,这可以通过将 Tree 和 GenericTree 类合并为一个来轻松解决。但请记住,这只是我的问题的一个例子。我自己的应用程序稍微复杂一些。
-
正如您所暗示的,解决方案是使 Tree 通用。您还暗示这是不可能的。为什么不呢?
-
在某些时候,我需要一个树列表。并且 Tree
的列表不会这样做,因为不允许我添加 Tree 实例。它当然会说 Tree 和 Tree 之间没有隐式引用。
标签: c# .net c#-4.0 generics casting