C#协变和抗变详解

简要介绍:

协变和抗变指对参数和返回值进行转换;

协变:按照继承链正向改变(实际上是向上兼容:子类向父类的转化)

逆变:按照继承链反向改变(实际上是向下兼容:父类向子类的转化)

下面说一下具体使用方式(在.net4之前,泛型接口没有协变和抗变)

一.不使用泛型接口的情况

//.net 参数类型是协变的返回类型是抗变的
public class Shape
    {
        public int Width { get; set; }
        public int Height { get; set; }
    }
public class Rectangle : Shape
    {
       
    }
public interface RSInterface
    {
        void Display(Shape o);
        Rectangle GetRectangle();
    }
public class RSClass : RSInterface
    {
        public int Rwidth { get; set; }
        public int Rheight { get; set; }
        public RSClass() { }
        public RSClass(int width, int height)
        {
            this.Rwidth = width;
            this.Rheight = height;
        }
        /// <summary>
        /// 实现协变操作
        /// </summary>
        /// <param name="o"></param>
        public void Display(Shape o)
        {
            Console.WriteLine($"width:{o.Width};height:{o.Height}");
        }
        /// <summary>
        /// 实现抗变操作
        /// </summary>
        /// <returns></returns>
        public Rectangle GetRectangle()
        {
            Rectangle rectangle = new Rectangle();
            rectangle.Width = this.Rwidth;
            rectangle.Height = this.Rheight;
            return rectangle;
        }
    }
//控制台输出
            RSInterface rS = new RSClass(26, 15);
            //协变
            rS.Display(new Rectangle { Width = 5, Height = 4 });
            //抗变
            Shape shape = rS.GetRectangle();
            Console.WriteLine($"width:{shape.Width};height:{shape.Height}");
            Console.ReadLine();

二.使用泛型接口的情况(使用out关键字代表协变,使用in关键字代表抗变)

  public class Shape
    {
        public int Width { get; set; }
        public int Height { get; set; }
    }
  public class Rectangle : Shape
    {
       
    }
  public interface RSInterface<in Shape, out Rectangle>
    {
        void Display(Shape o);
        Rectangle GetRectangle();
    }
 public class RSClass : RSInterface<Shape, Rectangle>
    {
        public int Rwidth { get; set; }
        public int Rheight { get; set; }
        public RSClass() { }
        public RSClass(int width, int height)
        {
            this.Rwidth = width;
            this.Rheight = height;
        }
        /// <summary>
        /// 抗变 向下兼容
        /// </summary>
        /// <param name="o"></param>
        public void Display(Shape o)
        {
            Console.WriteLine($"width:{o.Width};height:{o.Height}");
        }
        /// <summary>
        /// 协变 向上兼容
        /// </summary>
        /// <returns></returns>
        public Rectangle GetRectangle()
        {
            Rectangle shape = new Rectangle();
            shape.Height = this.Rheight;
            shape.Width = this.Rwidth;
            return shape;
        }
    }
//控制台输出
            RSInterface<Rectangle,Shape> rS = new RSClass(26, 15);
            //抗变
            rS.Display(new Rectangle { Width = 5, Height = 4 });
            //协变
            Shape shape = rS.GetRectangle();
            Console.WriteLine($"width:{shape.Width};height:{shape.Height}");
            Console.ReadLine();

猜你喜欢

转载自blog.csdn.net/qq_31975127/article/details/85157087