小議泛型

          Posted on 2008-09-22 19:25 H2O 閱讀(220) 評論(0)  編輯  收藏 所屬分類: java
          泛型
          一、什么是泛型?
          通過泛型可以定義類型安全類,而不會損害類型安全、性能或工作效率

          二、實例化泛型
          1、可以使用任何類型來聲明和實例化
          2、申明和實例話都必須用一個特定的類型來代替一般類型T
          3、例子:
          //原來寫法
          Public   class   Stack
          {
          object[]   m_Items;
          public   void   Push(object   item)
          {...}
          public   object   Pop()
          {...}
          }
          Stack   stack   =   new   Stack();
          stack.Push(1);
          int   number   =   (int)stack.Pop();

          //有了泛型后
          Public   class   Stack <T>
          {
          T[]   m_Items;
          public   void   Push(T   item)
          {...}
          public   T   Pop()
          {...}
          }
          Stack <int>   stack   =   new   Stack <int> ();
          stack.Push(1);
          int   number   =   (int)stack.Pop();

          三:泛型的好處
          1、一次性的開發、測試和部署代碼,通過任何類型來重用它
          2、編譯器支持和類型安全
          3、不會強行對值類型進行裝箱和取消裝箱,或者對引用類型進行向下強制類型轉換,所以性能得到顯著提高。
          注:值類型大概可以提高200%,引用類型大概為100%

          四:多個泛型
          1、單個類型可以定義多個泛型

          五:泛型別名
          1、在文件頭部使用using   為特定類型取別名,別名作用范圍是整個文件
          2、例子
          using   List   =   LinkedList <int,string> ;
          class   ListClient
          {
          static   void   Main(string[]   args)
          {
          List   list   =   new   List();
          list.AddHead(123, "AAA ");
          }
          }

          五:泛型約束
          (1)、派生約束
          如:
          public   class   LinkedList <K,T>   where   K:IComparable
          {
          T   Find(K   key)
          {
          if   (str.Key.CompareTo(key)   ==   0)//只有實現這個接口才可比較
          }
          }

          注意:
          1、所有的派生約束必須放在類的實際派生列表之后
          如:public   class   LinkedList <K,T> :IEnumerable <T>   where   K:IComparable <K>
                  {...}
          2、一個泛型參數上可以約束多個接口(用逗號分隔)
          public   class   LinkedList <K,T>   where   K:IComparable <K> ,IConvertible
          3、在一個約束中最多只能使用一個基類
          4、約束的基類不能是密封類或靜態類
          5、不能將System.Delegate或System.Array約束為基類
          6、可以同時約束一個基類以及一個或多個接口,但是該基類必須首先出現在派生約束列表中。
          7、C#允許你將另一個泛型參數指定為約束
          public   class   MyClass <T,U>   where   T:U
          {...}
          8、可以自己定義基類或接口進行泛型約束
          9、自定義的接口或基類必須與泛型具有一致的可見性

          (2)、構造函數約束
          如:
          class   Node   <K,T>   where   T:new()
          {
          }
          注意:
          1、可以將構造函數的約束和派生約束結合起來,前提是構造函數的約束出現在約束列表中的最后

          (3)、引用/值類型約束
          1、可以使用struct約束將泛型參數約束為值類型(如int、bool、enum),或任何自定義結構
          2、同樣可以使用class約束將泛型參數約束為引用類型
          3、不能將引用/值類型約束與基類約束一起使用,因為基類約束涉及到類
          4、不能使用結構和默認構造函數約束,因為默認構造函數約束也涉及到類
          5、雖然您可以使用類和默認構造函數約束,但是這樣做沒有任何價值
          6、可以將引用/值類型約束與接口約束組合起來,前提是引用/值類型約束出現在約束列表的開頭

          六:泛型和強制類型轉換
          1、C#編譯器只允許將泛型參數隱式轉換到Object或約束指定的類型
          如:
          interface   IS{...}
          class   BaseClass{...}
          class   MyClass <T>   where   T:BaseClass,IS
          {
          void   SomeMethod(T   t)
          {
          IS   obj1   =   t;
          BaseClass   obj2   =   t;
          object   obj3   =   t;
          }
          }
          2、編譯器允許你將泛型參數顯示強制轉換到其他任何借口,但不能將其轉換到類
          interface   IS{...}
          class   SomeClass{...}
          class   MyClass   <T>   //沒有約束
          {
          void   SomeMethod(T   t)
          {
          IS   obj1   =   (IS)t;   //可以
          SomeClass   obj2   =   (SomeClass)t   //不可以
          }
          }
          3、可以使用臨時的Object變量,將泛型參數強制轉換到其他任何類型
          class   SomeClass{...}
          class   MyClass   <T>  
          {
          void   SomeMethod(T   t)
          {
          object   temp   =   t;
          SomeClass   obj   =   (SomeClass)temp;//可以
          }
          }
          注意:這里只是告訴你這樣寫是可以的,但是要不要這樣寫?不要這樣寫,因為如果t確實沒有繼承SomeClass編譯沒錯但是運行就會出錯
          4、解決上面強制轉換問題,可以使用is和as運算符進行判斷
          public   class   MyClass <T>
          {
          public   void   SomeMethod <T   t>
          {
          if   (t   is   int   ){...}
          if   (t   is   LinkedList <int,string> ){...}
          //如果泛型參數的類型是所查詢的類型,則is運算符返回true
          string   str   =   t   as   string;
          //如果這寫類型兼容,則as將執行強制類型轉換,否則將返回null
          if   (str   !=   null){...}
          LinkedList <int,string>   list   =   t   as   LinkedList <int,string> ;
          if   (list   !=   null){...}
          }
          }

          七:繼承和泛型
          1、在從泛型基類派生,可以提供類型實參,而不是基類泛型參數
          public   class   BaseClass <T> {...}
          public   class   SubClass:BaseClass <int>
          2、如果子類是泛型,而非具體的類型實參,則可以使用子類泛型參數作為泛型基類的指定類型
          public   class   BaseClass <TT> {...}
          public   class   SubClass <T> :BaseClass <T> {...}
          3、在使用子類泛型參數時,必須在子類級別重復在基類級別規定的任何約束
          4、基類可以定義其簽名使用泛型參數的虛禮方法,在重寫它們時,子類必須在方法簽名中提供相應的類型。
          如:
          public   class   BaseClass <T>
          {
          public   virtual   T   SomeMethod()
          {...}
          }
          public   class   SubClass:BaseClass <int>
          {
          public   override   int   SomeMethod()
          {...}
          }
          5、如果該子類是泛型,則它還可以在重寫時使用它自己的泛型參數
          public   class   SubClass <T> :BaseClass <T>
          {
          public   override   T   SomeMethod()
          {...}
          }
          6、你可以定義泛型接口、泛型抽象類,甚至泛型抽象方法。
          7、不能對泛型參數使用+或+=之類的運算符
          public   class   Calculator <T>
          {
          public   T   Add   (T   arg1,T   arg2)
          {
          return   arg1   +   arg2;//錯誤
          }
          }
          但是我們可以通過泛型抽象類、接口來實現在個功能,因為實現泛型抽象類、接口我們就已經明確傳一個參數了,就可以執行諸如+這樣的操作。

          八:泛型方法
          1、方法可以定義特定于其執行范圍的泛型參數
          public   class   MyClass <T>
          {
          public   void   MyMethod <X> (X   x)
          {...}
          }
          2、即使各包含類根本不使用泛型,你也可以定義方法特定的泛型參數
          public   class   MyClass
          {
          public   void   MyMethod <T> (T   t)
          {...}
          }
          注意:該功能只使用于方法,屬性,索引器只能使用在類的作用范圍中定義的泛型參數。
          3、調用泛型方法
          MyClass   obj   =   new   MyClass();
          obj.MyMethod <int> (3);
          也可以這樣:
          MyClass   obj   =   new   MyClass();
          obj.MyMethod(3);   //該功能稱為泛型推理
          4、泛型方法也可以有自己的泛型參數約束
          pubic   class   MyClass
          {
          public   void   SomeMethod <T> (T   t)   where   T:IComparable <T>
          {...}
          }
          5、子類方法實現不能重復在父級別出現的約束
          public   class   BaseClass
          {
          public   virtual   void   SomeMethod <T> (T   t)where   T:new()
          {...}
          }
          pubic   class   SubClass:BaseClass
          {
          public   override   void   SomeMethod <T> (T   t)//不能再有約束
          {...}
          }
          6、靜態方法
          靜態方法可以定義特定的泛型參數和約束
          public   class   MyClass <T>
          {
          public   static   T   SomeMethod <X> (T   t,X   x)
          {...}
          }
          int   number   =   MyClass <int> .SomeMethod <string> (3, "AAA ");
          或者:int   mumber   =   MyClass <int> .SomeMethod(3, "AAA ");

          九:泛型委托
          1、在某個類中定義的委托可以利用該類的泛型參數
          2、委托也可以定義自己的泛型參數

          posts - 0, comments - 21, trackbacks - 0, articles - 101

          Copyright © H2O

          主站蜘蛛池模板: 龙南县| 内乡县| 安陆市| 会宁县| 通河县| 广安市| 新昌县| 炎陵县| 南华县| 张家口市| 平阳县| 余江县| 西华县| 南雄市| 灌阳县| 营山县| 赤水市| 商河县| 克山县| 桃园县| 上林县| 湖北省| 新巴尔虎右旗| 靖州| 许昌市| 原平市| 钦州市| 锦州市| 北海市| 阿拉尔市| 岳阳县| 西和县| 龙海市| 蕲春县| 陇西县| 邢台市| 通化县| 铅山县| 福建省| 吉安市| 浦江县|