协方差方差

din*_*esh 2 c# contravariance

我对CoVariance和ContraVariance有一些疑问..请参阅以下代码..

interface IGetElement<out T>
{
    int Counter { get; }
    T GetNext();
}

interface IAddElement<in T>
{
    void Add(T t);
}

class Collection<T> : IAddElement<T>, IGetElement<T> where T : Fruit
{
    List<T> tList = new List<T>();

    private int _counter = 0;

    public int Count { get { return tList.Count; } }

    public void Add(T t)
    {
        tList.Add(t);
    }

    int IGetElement<T>.Counter
    {
        get { return _counter; }
    }

    public T GetNext()
    {
        return tList[_counter++];
    }

    public void Rset()
    {
        _counter = 0;
    }
}

abstract class Fruit
{
    public abstract void Taste();
}

class Apple : Fruit
{
    public override void Taste()
    {
        Console.WriteLine("Like Apple");
    }
}
Run Code Online (Sandbox Code Playgroud)

这是示例代码..现在客户端是

 static void Main(string[] args)
 {
        IGetElement<Fruit> covarience = new Collection<Apple>(); // CoVarience..

        IAddElement<Apple> contravarience = new Collection<Fruit>();//ContraVarience.. Compiling fine and working also fine... :)

        IGetElement<Fruit> fruits = new Collection<Apple>();

        IAddElement<Fruit> apples2 = fruits as IAddElement<Apple>;//Here its Compiler error : Cannot implicitly convert type 'Test.IAddElement<Test.Apple>' to 'Test.IAddElement<Test.Fruit>'. An explicit conversion exists (are you missing a cast?)  

        IAddElement<Apple> apples1 = fruits as IAddElement<Fruit>;//This is not posible  
        /* Why this is not possible..? In this case No Compiler Error But Run Time error ie., 
       apples1 is NULL.. I don't know why.. because.. in fruits cantains apple only but 
       It is unable it caste it as ContrVariantly..  ?------------1 */

        IAddElement<Apple> apples = fruits as IAddElement<Apple>;//This is posible 


        IGetElement<Fruit> f = apples as IGetElement<Apple>;//This is posible.. 
        /* Why this is posible.. ? here we are casting t as CoVariantly..
        If ------------1 is not posible how this would be posible... yes.. I am casting to    
        actual object which is not Null.. ? -----------2 */
  }
Run Code Online (Sandbox Code Playgroud)

请在评论源代码中回答我的问题...... :) -------- 1,--------- 2.

谢谢和问候,Dinesh

Eri*_*ert 5

为了扩大詹姆斯的回答:

  1. 为什么这不可能?在这种情况下,没有编译器错误,但在运行时,apples1为null.我不知道为什么.

运行时的局部变量果实是指类型的对象Collection<Apple>.也就是说,只包含苹果的集合.

你在问"我可以在这个系列中添加任何水果吗?" 不,你只能加苹果,不能加任何水果.因此结果为null.

这在运行时而不是在编译时失败的原因是因为水果的编译时类型是接口类型,并且您将其转换为不同的接口类型.任何两个接口都可以由给定对象实现; 编译器不进行流分析以确定仅为水果分配了一种特定类型.因此,直到运行时才能进行检查.

  1. 为什么这是可行的?在这里,我们正在共同转换.

这里有两次转换.先将苹果转换为IGetElement<Apple>然后将其共同转换为IGetElement<Fruit>.

第一次转换成功,因为局部变量apples指的Collection<Apple>是实现的IGetElement<Apple>.你在问"这个对象能给我一个苹果吗?" 答案是肯定的.

第二次转换成功,因为编译器知道"可以递给我一个苹果的对象"可以被安全地视为"可以递给我一个水果的对象".

那现在清楚了吗?