<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      《CLR Via C# 第3版》筆記之(十四) - 泛型高級

      為了更好的利用泛型,現將泛型的一些高級特性總結一下。

      主要內容:

      • 泛型的協變和逆變
      • 泛型的參數的約束

      1. 泛型的協變和逆變

      對于泛型參數(一般用T表示),指定了類型之后。就只能識別此類型,面向對象中的繼承并不適用泛型參數,比如T指定為ClassA,盡管ClassB是ClassA的子類,也不能代替ClassA來作為泛型參數。

      但是,利用泛型的協變和逆變之后,我們可以寫出更加靈活的泛型代碼,避免不必要的強制轉型操作。

      首先看下面的示例代碼:

      using System;
      
      class CLRviaCSharp_14
      {
          // 泛型委托,其中委托的參數和返回值都是泛型
          public delegate TResult Print<T, TResult>(T arg);
      
          static void Main(string[] args)
          {
              ClassA a = new ClassA();
              ClassB b = new ClassB();
              ClassC c = new ClassC();
      
              Print<ClassB, ClassB> p1 = new Print<ClassB, ClassB>(Show);
              // 此處無法賦值,會報錯
              Print<ClassC, ClassB> p2 = p1;
              Console.WriteLine(p2(c).ToString());
              // 此處無法賦值,會報錯
              Print<ClassB, ClassA> p3 = p1;
              Console.WriteLine(p3(b).ToString());
      
              Console.ReadKey();
          }
      
          static ClassB Show(ClassB b)
          {
              return (ClassB)b;
          }
      }
      
      class ClassA
      {
          public override string ToString()
          {
              return "This is Class A!";
          }
      }
      
      class ClassB : ClassA
      {
          public override string ToString()
          {
              return "This is Class B!";
          }
      }
      
      class ClassC : ClassB
      {
          public override string ToString()
          {
              return "This is Class C!";
          }
      }

      上面有兩處地方無法編譯通過,分別是

      1. p2的參數類型ClassC無法轉換為p1的參數類型ClassB

      2. p1的返回值類型ClassB無法轉換為p3的返回值類型ClassA

      上面這2點其實都是 子類=>父類 的過程,在C#中是很自然的轉換。

      通過泛型的協變和逆變,也可以實現上面的轉換。

      上面的代碼只需改動一行就可以編譯成功,即改變其中委托的定義,加入協變和逆變的關鍵字in和out

          // 泛型委托,其中委托的參數和返回值都是泛型
          // in表示逆變, 即輸入參數的類型可由基類改為派生類
          // out表示協變,即返回值類型可以由派生類改為基類
          public delegate TResult Print<in T, out TResult>(T arg);

      這里需要強調一點的是,不管協變和逆變,其本質都是子類代替父類,并沒有違反面向對象的Liscov原則。

      首先看逆變,因為參數類型由基類變成了派生類,那么函數內部的使用基類完成的操作都可以用派生類來替換。

      再看協變,返回值由派生類變成了基類,那么函數內部原有返回派生類的操作都可以隱式轉換為基類再返回。

      通過協變和逆變,我們就可以不用修改函數(即上例中的Show函數)的前提下,使其支持多種泛型委托。

      2. 泛型的參數的約束

      泛型的約束不僅不會限制泛型的靈活性,反而會由于限制了泛型的類型,從而寫出更有針對性的代碼。

      泛型的約束主要有3種:主要約束,次要約束,構造器約束。

      2.1 主要約束

      類型參數可以指定零個或一個主要約束。主要約束可以是一個引用類型,連個特殊的主要約束是class和struct

      指定一個主要約束,相當于通知編譯器:一個指定的類型實參要么是與約束類型相同的類型,要么是從約束類型派生的類型。

      using System;
      using System.IO;
      
      class CLRviaCSharp_14
      {
          static void Main(string[] args)
          {
              GenericClassA<string> ga = new GenericClassA<string>();              // 正確
              GenericClassA<int> ga1 = new GenericClassA<int>();                   // 錯誤
              GenericClassB<int> gb = new GenericClassB<int>();                    // 正確
              GenericClassB<string> gb1 = new GenericClassB<string>();             // 錯誤
              GenericClassC<int> gc = new GenericClassC<int>();                    // 錯誤
              GenericClassC<string> gc1 = new GenericClassC<string>();             // 錯誤
              GenericClassC<Stream> gc2 = new GenericClassC<Stream>();             // 正確
              GenericClassC<FileStream> gc3 = new GenericClassC<FileStream>();     // 正確
      
              Console.ReadKey();
          }
      }
      
      // T必須是引用類型
      class GenericClassA<T> where T : class
      {    
      }
      
      // T必須是值類型
      class GenericClassB<T> where T : struct
      {
      }
      
      // T必須是Stream類型或者Stream類型的派生類型
      class GenericClassC<T> where T : Stream
      {
      }

      2.2 次要約束

      類型參數可以指定零個或多個次要約束。主要約束代表一個接口類型。

      指定一個次要約束,相當于通知編譯器:一個指定的類型實參要么是實現了指定接口的一個類型。

      using System;
      using System.IO;
      
      class CLRviaCSharp_14
      {
          static void Main(string[] args)
          {
              // 錯誤,string實現了IComparable但是沒有實現IDisposable
              GenericClassD<string> gd = new GenericClassD<string>();
              // 正確,ClassD既實現了IDisposable也實現了IComparable
              GenericClassD<ClassD> gd1 = new GenericClassD<ClassD>();
              // 錯誤,Stream實現了IDisposable但是沒有實現IComparable
              GenericClassD<Stream> gd2 = new GenericClassD<Stream>();
      
              Console.ReadKey();
          }
      }
      
      class GenericClassD<T> where T : IDisposable, IComparable
      {
          
      }
      
      class ClassD : IDisposable, IComparable
      {
          #region IDisposable Members
      
          public void Dispose()
          {
              throw new NotImplementedException();
          }
      
          #endregion
      
          #region IComparable Members
      
          public int CompareTo(object obj)
          {
              throw new NotImplementedException();
          }
      
          #endregion
      }

      3.3 構造器約束

      類型參數可以指定零個或一個構造器約束。

      指定一個構造器約束,相當于通知編譯器:一個指定的類型實參是實現了公共無參構造器的非抽象類型。

      using System;
      using System.IO;
      
      class CLRviaCSharp_14
      
          static void Main(string[] args)
          {
              // 錯誤,Stream是抽象類型
              GenericClassE<Stream> ge = new GenericClassE<Stream>();
              // 錯誤,FileStream沒有公共無參構造函數
              GenericClassE<FileStream> ge1 = new GenericClassE<FileStream>();
              // 正確,ClassE有公共默認無參構造函數,并且也是非抽象類型
              GenericClassE<ClassE> ge2 = new GenericClassE<ClassE>();
      
              Console.ReadKey();
          }
      
          static ClassB Show(ClassB b)
          {
              return (ClassB)b;
          }
      }
      
      class GenericClassE<T> where T : new()
      {
      }
      
      class ClassE
      {    
      }
      posted @ 2011-07-25 14:09  wang_yb  閱讀(837)  評論(0)    收藏  舉報
      主站蜘蛛池模板: 2021国产精品视频网站| 国产一区二区波多野结衣| 免费观看全黄做爰大片| 国产精品爆乳奶水无码视频免费 | 中文字幕精品无码一区二区| 中文字幕亚洲人妻系列| 久久精产国品一二三产品| 97成人碰碰久久人人超级碰oo| 日本亚洲色大成网站www久久| 中国女人内谢69xxxx| 国产亚洲无线码一区二区| 毛片大全真人在线| 国产成人精品无码片区在线观看| 国产成人综合亚洲欧美日韩| 国产精品揄拍一区二区久久| 亚洲AV永久纯肉无码精品动漫| 亚洲精品国模一区二区| 一区二区三区无码免费看| 国产一区二区三区日韩精品| 巨胸爆乳美女露双奶头挤奶| 午夜精品一区二区三区成人| 99精品国产中文字幕| 精品无码专区久久久水蜜桃| 国偷自产一区二区三区在线视频| 好紧好滑好湿好爽免费视频| 日本丰满少妇裸体自慰| 午夜精品极品粉嫩国产尤物| 欧美和黑人xxxx猛交视频| 中文字幕日韩精品一区二区三区| 久久综合色之久久综合色| 国产一区二区黄色激情片| 777久久精品一区二区三区无码 | 欧美人禽zozo动人物杂交| 国产成人啪精品午夜网站| 开心五月激情综合久久爱| 大地资源高清免费观看| 天天躁日日躁狠狠躁中文字幕| 国产精品不卡一区二区视频| 黑人异族巨大巨大巨粗| 熟妇人妻中文a∨无码| 美欧日韩一区二区三区视频|