c# - 协方差 反方差

标签 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");
    }
}

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

 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 */
  }

请在注释源代码中回答我的问题...:) ------1,--------2。

感谢和问候, 迪内什

最佳答案

进一步扩展 James 的回答:

  1. Why this is not possible? In this case there is no compiler error but at runtime apples1 is null. I don't know why.

运行时的局部变量 fruits 指的是类型为 Collection<Apple> 的对象.也就是说,一个仅包含苹果的集合。

您在问“我可以向这个系列中添加任何水果吗?”不可以。您只能添加苹果,不能添加任何水果。因此结果为空。

这在运行时而不是在编译时失败的原因是因为 fruit 的编译时类型是一种接口(interface)类型,而您正在将其转换为不同的接口(interface)类型。任何两个接口(interface)都可能由给定的对象实现;编译器不会进行流分析来确定 fruits 只被分配了一种特定类型。因此检查要到运行时才能完成。

  1. Why this is posible? Here we are converting covariantly.

这里有两个转换。第一个苹果被转换为IGetElement<Apple>然后将其协变转换为 IGetElement<Fruit> .

第一次转换成功,因为局部变量 apples 引用了一个 Collection<Apple>实现IGetElement<Apple> .你在问“这个物体能给我一个苹果吗?”答案是肯定的。

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

现在清楚了吗?

关于c# - 协方差 反方差,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7432447/

相关文章:

c# - 向 DataColumn 添加属性

contravariance - 为什么 Liskov 替换原则需要参数是逆变的?

c# - IComparer 和 IEqualityComparer 接口(interface)中逆变的好处

java - 应该删除(Object) 为删除(? super E)

c# - sqlite 抛出一个 "String not recognized as a valid datetime"

c# - ORA-01790 与 EntityFramework

c# - 从 MultipartFormDataContent 和 StreamContent 获取上传进度

c# - GetPrivateProfileString 不工作.NET

c# - 如何使用逆变参数将泛型接口(interface)转换为基类型?

c# - 支持单个类型参数的协变和逆变