接口中的协变和逆变

3
这是使用协变和逆变来处理泛型的示例。
 class Program
    {
        static void Main(string[] args)
        {
            ICovariant<Apple> alCov = new Covariant<Apple>();
            ICovariant<Fruite> fCov = alCov;

            IContravariant<Apple> aContra = new Contravariant<Apple>();
            IContravariant<Apple> fContra = new Contravariant<Fruite>();

        }


        public class Fruite
        {
            public virtual void Print()
            {
                Console.WriteLine("Fruite");
            }
        }

        public class Apple : Fruite
        {
            public override void Print()
            {
                Console.WriteLine("Apple");
            }
        }

        interface IContravariant<in T>
        {
            void Method();

            // This interface can be implicitly cast to MORE DERIVED (downcasting)
            // Usually means T is used as argument
            void Method(T argument);
        }//interface

        interface ICovariant<out T>
        {
            // This interface can be implicitly cast to LESS DERIVED (upcasting)
            // Used for readonly collections
            IEnumerable<T> GetList { get; }
            // Used when T is used as return type
            T Method();
        }//interface


        public class Covariant<T> : ICovariant<T>
        {
            public IEnumerable<T> GetList
            {
                get
                {
                    throw new NotImplementedException();
                }
            }

            public T Method()
            {
                throw new NotImplementedException();
            }
        }
        public class Contravariant<T> : IContravariant<T>
        {
            public void Method()
            {
                Console.Write(typeof(T));
            }

            public void Method(T argument)
            {
                Console.Write(argument);
            }
        }

    }

我理解这些代码,因为它类似于多态性,并且我理解其中的好处。

ICovariant<Apple> alCov = new Covariant<Apple>();
ICovariant<Fruite> fCov = alCov;

但我不明白逆变的好处,就像下面的代码一样。
IContravariant<Apple> aContra = new Contravariant<Apple>();
IContravariant<Apple> fContra = new Contravariant<Fruite>();

所以,有没有人能举例说明我如何从中受益。

1
IEqualityComparer<Fruite> c = new FruiteComparer(); var d = new HashSet<Apple>(c); - user4003407
1个回答

1

那么,有人能举例说明我如何从中受益吗?

使用示例可能如下:

 IContravariant<Fruite> fContra = new Contravariant<Fruite>();
 List<IContravariant<Apple>>  contravariants=  new List<IContravariant<Apple>>();
 contravariants.Add(fContra);
 contravariants.Add(aContra);

如果您将IContavariant<in T>接口更改为IContavariant<T>,则会出现编译时错误。

一个很好的例子是Linq中的Distinct方法,您可以想到一个执行相同操作但不使用IEqualityComparer<T>而对所有水果使用相同算法的方法。

在此链接中,您可以找到一个完整的示例比较通用集合


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接