C# - 是否有某种方式蒙上了泛型集合?方式

2023-09-05 00:08:41 作者:人情冷暖薄如纸

我一直忙于C#4.0泛型,现在我基本上想要做这样的事情:

I've been busy with C# 4.0 generics, and now I basically want to do something like this:

public abstract class GenericTree<T> : Tree
    where T : Fruit
{
    public Tree(IFruitCollection<T> fruits)
        : base(fruits) { }
}

基树类看起来是这样的:

The base Tree class looks like this:

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的实现:

Here is my first problem. The constructor of GenericTree can't cast the the generic collection to a fruit collection. I've also got an implementation of the GenericTree:

public class AppleTree : GenericTree<Apple>
{
    public AppleTree()
        : base(new FruitCollection<Apple>) { }
}

下面是我的第二个问题。当我添加水果苹果树的一个实例,使用myAppleTree.GetFruits.Add(...),我不是仅限于苹果。我允许添加各种水果。我不想这样。

Here's my second problem. When I add fruit to an instance of AppleTree, using myAppleTree.GetFruits.Add(...), I am not restricted to apples only. I am allowed to add all kinds of fruit. I don't want this.

我试图通过增加这对GenericTree来解决这个问题:

I tried to solve that problem by adding this to the GenericTree:

new public IFruitCollection<T> GetFruits
{
    get { return base.GetFruits as IFruitCollection<T>; }
}

但是,这也是不可能的。它在某种程度上总是返回null。这可能是可能的,这将得到解决,当我的第一个问题就解决了​​。

But this is not possible either. It somehow always returns null. It could be possible that this will be solved, when my first problem is solved.

在IFruitCollection界面看起来是这样的:

The IFruitCollection interface looks like this:

public interface IFruitCollection<T> : ICollection<T>
    where T : Fruit { ... }

而FruitCollection类是一个简单的实现集合类。 哦,当然,苹果类继承了水果类。

And the FruitCollection class is a simple implementation of the Collection class. Oh, and of course, the Apple class extends the Fruit class.

的解决方案是使与两个协方差和逆变的IFruitCollection接口兼容。但我怎么做到这一点?在进或出参数关键字是不可能的,因为ICollection接口不允许这样做。

The solution is to make the IFruitCollection interface compatible with both covariance and contravariance. But how do I achieve this? The "in" or "out" parameter keywords are not possible, because the ICollection interface doesn't allow it.

非常感谢您的帮助!

推荐答案

我想我找到了我的解决方案,而我尝试phoog的解决方法。谢谢你,phoog!

I think I found my solution, while I was trying out phoog's workaround. Thanks, phoog!

起初我没有给GenericTree自己FruitCollection。 Mosty因为基类经常遍历自己的收藏,比如更新的成果。这导致到水果没有更新,因为他们被添加到GenericTree的集合,而不是基地集合。

At first I didn't give GenericTree his own FruitCollection. Mosty because the base class often loops through his own collection, for example to update the fruits. This resulted into fruits not updating, because they were added to the GenericTree's collection, not to the base collection.

但最终我意识到,铸造这些收藏是永远不会擦出火花。

But eventually I realised that casting those collections is never going to work either.

现在我做了自动添加和删除组件的基础FruitCollection,反之亦然另一个FruitCollection类。该解决方案为我的伟大工程!

Now I've made another FruitCollection class that automatically adds and removes components to the base FruitCollection, and vice versa. This solution works great for me!

public FruitCollection<T, U> : FruitCollection<T>
    where T : U
    where U : Fruit
{
    private FruitCollection<U> baseCollection;

    public FruitCollection(FruitCollection<U> baseCollection)
        : base()
    {
        this.baseCollection = baseCollection;

        // here I added code that throws events whenever the collection is changed
        // I used those events to add/remove fruit to the base collection, and vice versa
        // see the link below.
        ...
    }

    ...
}

public class GenericTree<T>: Tree
    where T : Fruit
{
    private FruitCollection<T> fruits;

    // use the new keyword to hide the base collection
    new public FruiCollection<T> Fruits
    {
        get { return fruits; }
    }

    public GenericTree()
        : base()
    {
        // after hiding the base collection, use base.Fruits to get it
        fruits = new FruitCollection<T, Fruit>(base.Fruits);
    }
}

这帮助我:如何处理添加到列表事件

 
精彩推荐
图片推荐