c# – 继承的通用类型统一

对于这样的场景:

public interface IAnimal
{

}

public interface IGiraffe : IAnimal
{

}

public interface IQuestionableCollection : IEnumerable<IAnimal>
{
    void SomeAction();
}

public interface IQuestionableCollection<out T> : IQuestionableCollection, IEnumerable<T>
    where T : IAnimal
{

}

public class QuestionableCollection<T> : IQuestionableCollection<T>
    where T:IAnimal
{
    // Implementation... 
}

编译器会产生错误:

'IQuestionableCollection<T>' cannot implement both 'System.Collections.Generic.IEnumerable<IAnimal>' and 'System.Collections.Generic.IEnumerable<T>' because they may unify for some type parameter substitutions

这是有道理的,除非使用类型约束,否则C#无法解析的两个接口之间确实存在歧义,因为它不符合语言规范,因为@ericlippert解释了here.

我的问题是如何在这里实现相同的效果?

似乎我应该能够表示该集合是可枚举的基本接口. (我想提供一套可以在不知道具体类型的情况下可以使用的方法,以及它使一些API /反射代码更干净,所以我想将基础集合保持为非泛型,如果有的话可能,否则不需要两个接口.)

我可以想到的唯一的实现是这样的:

public interface IQuestionableCollectionBase
{
    void SomeAction();
}

public interface IQuestionableCollection : IQuestionableCollectionBase, IEnumerable<IAnimal>
{

}

public interface IQuestionableCollection<out T> : IQuestionableCollectionBase, IEnumerable<T>
    where T : IAnimal
{

}

public class QuestionableCollectionBase<T> : IQuestionableCollection
    where T : IAnimal
{
    protected List<T> _items = new List<T>();

    public void SomeAction() { }

    IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable)_items).GetEnumerator(); }
    IEnumerator<IAnimal> IEnumerable<IAnimal>.GetEnumerator() { return ((IEnumerable<IAnimal>)_items).GetEnumerator(); }
}

public class QuestionableCollection<T> : QuestionableCollectionBase<T>, IQuestionableCollection<T>
    where T : IAnimal
{
    public IEnumerator<T> GetEnumerator() { return ((IEnumerable<T>)_items).GetEnumerator(); }
}

请注意,我不得不将任何我想要在两个接口上使用的方法移动到一个基本方法,并且有两个级别的类本身实现 – 这似乎正在跳过这里的足够的箍,我已经缺少某物…

应该如何实施?

最简单的解决方法是将IEnumerables从“is-a”更改为“has-a”,如下所示:

public interface IAnimal { }
public interface IGiraffe : IAnimal { }

public interface IQuestionableCollection
{
    IEnumerable<IAnimal> Animals { get; }
    void SomeAction();
}

public interface IQuestionableCollection<out T> : IQuestionableCollection
    where T : IAnimal
{
    new IEnumerable<T> Animals { get; }
}

public class QuestionableCollection<T> : IQuestionableCollection<T>
    where T : IAnimal, new()
{
    private readonly List<T> list = new List<T>();

    public IEnumerable<T> Animals
    {
        get { return list; }
    }

    IEnumerable<IAnimal> IQuestionableCollection.Animals
    {
        get { return (IEnumerable<IAnimal>)list; }
    }

    public void SomeAction()
    {
        list.Add(new T());
    }
}

class Giraffe : IGiraffe { }

[TestMethod]
public void test()
{
    var c = new QuestionableCollection<Giraffe>();
    IQuestionableCollection<Giraffe> i = c;
    IQuestionableCollection<IGiraffe> i2 = i;

    Assert.AreEqual(0, c.Animals.Count());
    Assert.AreEqual(0, i.Animals.Count());
    c.SomeAction();
    i.SomeAction();
    Assert.AreEqual(2, c.Animals.Count());
    Assert.AreEqual(2, i.Animals.Count());
}

请注意,您可以避免在QuestionableCollection< T>如果你添加一个T:class约束.

http://stackoverflow.com/questions/29907762/inherited-generic-type-unification

转载注明原文:c# – 继承的通用类型统一