zoukankan      html  css  js  c++  java
  • 13.3.2 在接口中使用可变性

    1. 用 in 和 out 表示可变性

    我们使用的两个接口是 IEnumerable<T> (对于 T 是协变的)和 IComparer<T> (对于 T 是逆变的),它们可以很好地展示可变性。以下是它们在.NET 4中的声明:

        public interface IEnumerable<out T>
        public interface IComparer<in T>

    这非常好记:如果类型参数只用于输出,就使用 out ;如果只用于输入,就用 in 。编译器可不知道你是否记住了哪种形式是协变,哪种形式是逆变。

     1     public interface IShape
     2     {
     3         double Area { get; }
     4 
     5         System.Windows.Rect BoundingBox { get; }
     6     }
     7     /// <summary>
     8     /// WindowsBase.dll下
     9     /// </summary>
    10     public sealed class Circle : IShape
    11     {
    12         private readonly System.Windows.Point center;
    13         public System.Windows.Point Center { get { return center; } }
    14 
    15         private readonly double radius;
    16         public double Radius { get { return radius; } }
    17 
    18         public Circle(System.Windows.Point center, int radius)
    19         {
    20             this.center = center;
    21             this.radius = radius;
    22         }
    23 
    24         public double Area
    25         {
    26             get { return Math.PI * radius * radius; }
    27         }
    28 
    29         public System.Windows.Rect BoundingBox
    30         {
    31             get
    32             {
    33                 return new System.Windows.Rect(center - new System.Windows.Vector(radius, radius), new System.Windows.Size(radius * 2, radius * 2));
    34             }
    35         }
    36     }
    37     public sealed class Square : IShape
    38     {
    39         private readonly Point topLeft;
    40         private readonly double sideLength;
    41 
    42         public Square(Point topLeft, double sideLength)
    43         {
    44             this.topLeft = topLeft;
    45             this.sideLength = sideLength;
    46         }
    47 
    48         public double Area { get { return sideLength * sideLength; } }
    49 
    50         public Rect BoundingBox
    51         {
    52             get { return new Rect(topLeft, new Size(sideLength, sideLength)); }
    53         }
    54     }
    View Code

    2. 接口的协变性

     1             List<Circle> circles = new List<Circle>()
     2             {
     3                 new Circle(new Point(0, 0), 15),
     4                 new Circle(new Point(10, 5), 20),
     5             };
     6             List<Square> squares = new List<Square>()
     7             {
     8                 new Square(new Point(5, 10), 5),
     9                 new Square(new Point(-10, 0), 2),
    10             };
    11 
    12             List<IShape> shapesByAdding = new List<IShape>();
    13             shapesByAdding.AddRange(circles);
    14             shapesByAdding.AddRange(squares);
    15             List<IShape> shapesByConcat = circles.Concat<IShape>(squares).ToList();

    实际上,代码清单13-12在4个地方使用了协变性,对于类型系统而言,每次将圆形或方形序列转换为普通几何形状时,都用到了协变性。
    首先新建了一个 List<IShape> ,并调用 AddRange向其添加圆形和方形列表 。(我们也可以向构造函数传递一个列表,然后调用 AddRange 一次。)
    List<T>.AddRange 的参数为 IEnumerable<T> 类型,因此在这种情况下我们将这两个列表都看成是 IEnumerable<IShape> ,而这在以前是不被允许的。

    3. 接口的逆变性

     1     class Program
     2     {
     3         static void Main(string[] args)
     4         {
     5             List<Circle> circles = new List<Circle>()
     6             {
     7                 new Circle(new Point(0, 0), 15),
     8                 new Circle(new Point(10, 5), 20),
     9             };
    10             List<Square> squares = new List<Square>()
    11             {
    12                 new Square(new Point(5, 10), 5),
    13                 new Square(new Point(-10, 0), 2),
    14             };
    15 
    16             IComparer<IShape> areaComparer = new AreaComparer();
    17             circles.Sort(areaComparer);
    18         }
    19     }
    20     class AreaComparer : IComparer<IShape>
    21     {
    22         public int Compare(IShape x, IShape y)
    23         {
    24             return x.Area.CompareTo(y.Area);
    25         }
    26     }
  • 相关阅读:
    mysql 脚本
    一:spring boot 第一个程序启动遇到的问题及应对方案
    abp单元测试报错,出现异常解决办法 (system.directoryservices.protocols不能load该对象)
    如何实现 linq子查询
    Some times
    我的外婆
    男人之所以男人
    搭建自己网站【比如:博客】的方法
    搭建自己网站【比如:博客】的方法
    搭建自己网站【比如:博客】的方法
  • 原文地址:https://www.cnblogs.com/kikyoqiang/p/10105698.html
Copyright © 2011-2022 走看看