本文介绍了泛型方法可以使用逆变/协变的类型?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在书面方式T4模板使用它在一个特殊任务的通用方法。该方法应该允许我使用特定类型从一般的接口。我想到了以下特征:

 接口IGreatInterface {
对象aMethodAlpha< U>(U参数),其中U: IAnInterface;
对象aMethodBeta(IAnInterface参数)
}

公共类AnInterestingClass:IAnInterface {}

当我尝试实施 IGreatInterface 编译器标志 aMethodBeta错误()因为我做了我的T4编写使用 IAnInterface 的子类型的方法(即我想要实现像这样的方法:对象aMethodBeta(AnInterestingClass参数)



方法 aMethodAlpha< U>()可以使用,但是不是干净,因为我想,因为我的T4有可能产生一些额外的代码。我(也许错误地)
建议该方法中,其具有由一T4来完成的实施方案,可将结果
对象aMethodAlpha&所述; AnInterestingClass>(AnInterestingClass参数)



我在想,一般的方法不支持逆变类型,但我不知道;我想,这是编译防止编码器使用具有在一般类型没有定义的方法的特定类型的方式...




  • 是否泛型方法必须使用的确切类型正在实施的时候?

  • 有没有什么绝招来改变这种行为?


  • 解决方案

    这个问题是相当混乱。让我看看,如果我可以澄清。



    That's not legal. Simplifying somewhat:

    class Food {}
    class Fruit : Food {}
    class Meat : Food {}
    interface IEater
    {
        void Eat(Food food);
    }
    class Vegetarian : IEater
    {
        public void Eat(Fruit fruit);
    }
    

    Class Vegetarian does not fulfill the contract of IEater. You should be able to pass any Food to Eat, but a Vegetarian only accepts Fruit. C# does not support virtual method formal parameter covariance because that is not typesafe.

    Now, you might then say, how about this:

    interface IFruitEater
    {
        void Eat(Fruit fruit);
    }
    class Omnivore : IFruitEater
    {
        public void Eat(Food food);
    }
    

    Now we have got type safety; Omnivore can be used as an IFruitEater because an Omnivore can eat fruit, as well as any other food.

    Unfortunately, C# does not support virtual method formal parameter type contravariance even though doing so is in theory typesafe. Few languages do support this.

    Similarly, C# does not support virtual method return type variance either.

    I'm not sure if that actually answered your question or not. Can you clarify the question?

    UPDATE:

    What about:

    interface IEater
    {
        void Eat<T>(T t) where T : Food;
    }
    class Vegetarian : IEater
    {
        // I only want to eat fruit!
        public void Eat<Fruit>(Fruit food) { }
    }
    

    Nope, that's not legal either. The contract of IEater is that you will provide a method Eat<T> that can take any T that is a Food. You cannot partially implement the contract, any more than you could do this:

    interface IAdder
    {
        int Add(int x, int y);
    }
    class Adder : IAdder
    {
        // I only know how to add two!
        public int Add(2, int y){ ... }
    }
    

    However, you can do this:

    interface IEater<T> where T : Food
    {
        void Eat(T t);
    }
    class Vegetarian : IEater<Fruit>
    {
        public void Eat(Fruit fruit) { }
    }
    

    That is perfectly legal. However, you cannot do:

    interface IEater<T> where T : Food
    {
        void Eat(T t);
    }
    class Omnivore : IEater<Fruit>
    {
        public void Eat(Food food) { }
    }
    

    Because again, C# does not support virtual method formal parameter contravariance or covariance.

    Note that C# does support parametric polymorphism covariance when doing so is known to be typesafe. For example, this is legal:

    IEnumerable<Fruit> fruit = whatever;
    IEnumerable<Food> food = fruit;
    

    A sequence of fruit may be used as a sequence of food. Or,

    IEnumerable<Fruit> fruitComparer = whatever;
    IComparable<Apples> appleComparer = fruitComparer;
    

    If you have something that can compare any two fruits then it can compare any two apples.

    However, this kind of covariance and contravariance is only legal when all of the following are true: (1) the variance is provably typesafe, (2) the author of the type added variance annotations indicating the desired co- and contra-variances, (3) the varying type arguments involved are all reference types, (4) the generic type is either a delegate or an interface.

    这篇关于泛型方法可以使用逆变/协变的类型?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

    07-30 15:55