zoukankan      html  css  js  c++  java
  • C# 高级编程(笔记3)

    第5章  泛型

    1.泛型类的静态成员
      泛型类的静态成员只能在类的一个实例中共享

      public class staticDemo<T>
      {
        public static int x;
      }

    由于同时对一个string类型和一个int类型使用了staticDemo<T>类,所以存在两组静态字段:

    staticDemo<string>.x = 4; 
    staticDemo<int>.x = 5;
    Console.WriteLine(staticDemo<string>.x); //输出 4

    2.协变和抗变:指对参数和返回值的类型进行转换
    假定有Shape和Rectangle类,Rectangle派生自Shape基类。声明Display()方法是为了接受Shape类型的对象作为其参数:

      (1)
      public void Display(Shape o) { }
      ----现在可以传递派生自Shape基类的任意对象。因为Rectangle派生自Shape基类,所以Rectangle满足Shape的所有要求,编译器接受这个方法的调用:
      Rectangle r = new Rectangle { Width= 5, Height=2.5};
      Display(r);//子类转父类,协变的作用

      (2)
      当方法返回一个Shape时,不能把它赋予Rectangle,因为Shape不一定总是Rectangle。反过来是可行的: 
      public Rectangle GetRectangle();
      Shape s = GetRectangle();

      对于上面的(1)(2)行为,在.net4版本之前,这种行为方式不适用于泛型。但在.net4中,扩展后的语言支持泛型接口和泛型委托的协变和抗变。
     
      也就是可以这样:ITest<Shape> shape = ITest<Rectangle> rectangle;//协变

      A.协变:子类向父类方向转变  ----------------- 参数类型是协变的。   

      B.抗变:父类向子类方向转变,不一定能转成功  ----------------- 方法的返回类型是抗变的。

    3.泛型接口的协变

       如果泛型类型用 out 关键字标注,泛型接口就是协变的。这也意味着返回类型只能是T。下面的IIndex与类型T是协变的,并从一个只读索引器返回这个类型

      public interface IIndex<out T>
      {
          T this[int index]{get;}
          int Count{get;}
      }

    下面用RectangleCollection类来实现接口IIndex<out T>,RectangleCollection类为泛型类型T定义了Rectangle:

      public class RectangleCollection: IIndex< Rectangle >
      {
          public static Rectangle[] data = new Rectangle[3]
          {
              new Rectangle { Height=2, Width=5},
              new Rectangle { Height=3, Width=7},
              new Rectangle { Height=4.5, Width=2.9}
          };
    
          public static RectangleCollection GetRectangles()
          {
              return new RectangleCollection();
          }
    
          public Rectangle this[int index]
          {
              get
              {
                  if (index < 0 || index > data.Length)
                      throw new ArgumentOutOfRangeException("index");
                  return data[index];
              }
          }
          
          public int Count
          {
             get
             {
                 return data.Length;
             }
          } 
          
      }

    ----由上面可以看出,RectangleCollection.GetRectangles()返回一个实现IIndex< Rectangle >接口的RectangleCollection类,所以可以把返回值赋予IIndex<Rectangle>类型的变量rectangle。

         因为接口是协变的,所以也可以把返回值赋予IIndex<Shape>类型的变量。【Rectangle继承于Shape】

     static void Main()
     {
        IIndex<Rectangle> rectangles = RectangleCollection.GetRectangles();
        IIndex<Shape> shapes = rectangles;
        for (int i = 0; i < shapes.Count; i++)
        {
            Console.WriteLine(shapes[i]);
        }
     }

    4.泛型接口的抗变
       如果泛型类型用 in 关键字标注,泛型接口就是抗变的。这样,接口只能把泛型类型T用作其方法的参数类型,而不能用作其方法的返回值类型

      public interface IDisplay<in T>
      {
         void Show(T item);
      }
    
      ShapeDisplay类实现IDisplay<Shape>,并使用Shape对象作为输入参数:
      
      public class ShapeDisplay: IDisplay<Shape>
      {
          public void Show(Shape s)
          {
              Console.WriteLine("{0} Width: {1}, Height: {2}", s.GetType().Name,
              s.Width, s.Height);
          }
      }
    
      ----创建ShapeDisplay的一个新实例,会返回IDisplay<Shape>,并把它赋予shapeDisplay变量。因为IDisplay<T>是抗变的,所以可以把结果赋予IDisplay<Rectangle>,其中Rectangle类派生自Shape。
    
      static void Main()
      {
         //...
         IDisplay<Shape> s = new ShapeDisplay();
         IDisplay<Rectangle> r = s;//抗变,父类向子类方向转变
         rectangleDisplay.Show(RectangleCollection.data[0]);
      }
  • 相关阅读:
    jenkins2.0以后的版本提供自动部署和远程部署功能?
    测试之路之同事
    jmeter分布式压力测试实践+登录为例
    模板渲染jnja2模块
    10 分离式web框架
    09 基于模块wsgiref版web框架
    08 返回动态页面web框架
    07 返回多个页面web框架
    06 返回静态文件的映射(函数/多线程)web框架
    05 返回静态文件的多线程web框架
  • 原文地址:https://www.cnblogs.com/notebook2011/p/2969630.html
Copyright © 2011-2022 走看看