程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> 關於.NET >> 泛型相關知識

泛型相關知識

編輯:關於.NET

自從上次參加完俱樂部的聚會後,覺的有必要總結下泛型的用法,雖然腦袋講的 非常仔細,沒有必要再寫,但做為學習者,我喜歡把自己的所學以文章的形式展示出 來,這樣也有我的一部分。我們可以用一個簡單的例子來做實驗:實例化一個 ArrayList和一個List<int>,然後往其中加入成員,最後分別讀取出第一個 成員,進行一個加法操作。

  ArrayList _list = new ArrayList();

            _list.Add(1);

            _list.Add("a");

         

            int i = (int)_list[0]  + 1;

            List<int> _list2 = new List<int>();

            _list2.Add(1);//正確

         

            int j = (int)_list2[0] + 1;

ArrayList的缺點:

1:處理值類型時,出現裝箱、折箱操作,影響性能。_list.Add(1)時會發生裝 箱。

2:處理引用類型時,雖沒有裝箱和折箱操作,但仍需要類型轉換操作。代碼 _list.Add("a")不會發生裝箱。

3:程序運行時的類型轉換可能引發異常。運行_list[1]時,由於它是一個字符 串,要強制轉換成int就會有異常。

泛型處理過程:泛型用一個通用的數據類型T來代替object,在類實例化時指 定T的類型,CLR自動編譯為本地代碼,並且保證數據類型安全。

泛型優點:

1:類型安全的。例如實例化了int類型的類,就不能處理string類型的數據。 上面的_list2.Add("a"),就會報錯。

2:處理值類型時,無需裝箱和折箱。int j=i+1;i可以直接取,並不需要折箱操 作。

3:無需類型轉換,包含值類型和引用類型。

我們來看下它生成的IL代碼:

// 代碼大小       72 (0x48)

  .maxstack  2

  .locals init ([0] class [mscorlib]System.Collections.ArrayList 

_list,

           [1] int32 i,

           [2] class [mscorlib]

System.Collections.Generic.List`1<int32> _list2,

           [3] int32 j)

  IL_0000:  nop

  IL_0001:  newobj     instance void [mscorlib]

System.Collections.ArrayList::.ctor()

  IL_0006:  stloc.0

  IL_0007:  ldloc.0

  IL_0008:  ldc.i4.1

  IL_0009:  box        [mscorlib]System.Int32

  IL_000e:  callvirt   instance int32 [mscorlib]

System.Collections.ArrayList::Add(object)

  IL_0013:  pop

  IL_0014:  ldloc.0

  IL_0015:  ldstr      "a"

  IL_001a:  callvirt   instance int32 [mscorlib]

System.Collections.ArrayList::Add(object)

  IL_001f:  pop

  IL_0020:  ldloc.0

  IL_0021:  ldc.i4.0

  IL_0022:  callvirt   instance object [mscorlib]

System.Collections.ArrayList::get_Item(int32)

  IL_0027:  unbox.any  [mscorlib]System.Int32

  IL_002c:  ldc.i4.1

  IL_002d:  add

  IL_002e:  stloc.1

  IL_002f:  newobj     instance void class [mscorlib]

System.Collections.Generic.List`1<int32>::.ctor()

  IL_0034:  stloc.2

  IL_0035:  ldloc.2

  IL_0036:  ldc.i4.1

  IL_0037:  callvirt   instance void class [mscorlib]

System.Collections.Generic.List`1<int32>::Add(!0)

  IL_003c:  nop

  IL_003d:  ldloc.2

  IL_003e:  ldc.i4.0

  IL_003f:  callvirt   instance !0 class [mscorlib]

System.Collections.Generic.List`1<int32>::get_Item(int32)

  IL_0044:  ldc.i4.1

  IL_0045:  add

  IL_0046:  stloc.3

  IL_0047:  ret

第一:ArrayList與List<T>的構造函數說明了泛型的類型安全優點:

1:實例化ArrayList:

IL_0001:  newobj     instance void [mscorlib]

System.Collections.ArrayList::.ctor()

2:實例化List<T>:

IL_002f:  newobj     instance void class [mscorlib]

System.Collections.Generic.List`1<int32>::.ctor()

第二:IL_0009:  box        [mscorlib]System.Int32這條語句表 明一個整數被加入到ArrayList時會出現裝箱。而List<int>的IL代碼中並 沒有出現box語句。這點可以證明泛型的優點二。

第三:兩者讀取成員的操作不同可以說明泛型的優點三。

1:下面的語句表明當從ArrayList中讀取一個成員時,需要進行拆箱操作。

IL_0022:  callvirt   instance object [mscorlib]

System.Collections.ArrayList::get_Item(int32)

  IL_0027:  unbox.any  [mscorlib]System.Int32

2:下面的代碼表明從List<int>中讀取一個成員時,不需要進行拆箱操 作。

IL_003f:  callvirt   instance !0 class [mscorlib]

System.Collections.Generic.List`1<int32>::get_Item(int32)

  IL_0044:  ldc.i4.1

泛型類實例化的理論:C#泛型類在編譯時,先生成中間代碼IL,通用類型T只 是一個占位符。在實例化類時,根據用戶指定的數據類型代替T並由即時編譯器 (JIT)生成本地代碼,這個本地代碼中已經使用了實際的數據類型。

泛型中的靜態成員變量:在C#1.x中,類的靜態成員變量在不同的類實例間是 共享的,C#2.0中,靜態成員變量在相同封閉類間共享,不同的封閉類間不共享。示 例代碼:

public partial class _Default : System.Web.UI.Page

    {

        protected void Page_Load(object sender, EventArgs e)

        {

            Point<int> _point = new Point<int>

(1);

            Point<int> _point2 = new Point<int>

(2);

            Point<long> _point3 = new 

Point<long>(3);

            string  width1 = _point.ToString();//結果為2

            string  width2 = _point2.ToString();//結果為2

            string width3 = _point3.ToString();//結果為3

            //width1和width2相等,但和width3不等,說明了靜態成

員變量在相同封閉類間共享,

            不同的封閉類間不共享。          

        }

    }

    /// <summary>

    /// 一個泛型類,接受一個T

    /// </summary>

    /// <typeparam name="T"></typeparam>

    public class Point<T>

    {

        /// <summary>

        /// 靜態變量

        /// </summary>

        public static T width;

        /// <summary>

        /// 構造函數

        /// </summary>

        /// <param name="_width"></param>

        public Point(T _width)

        {

            width = _width;

        }

        /// <summary>

        /// 輸出width值

        /// </summary>

        /// <returns></returns>

        public override string ToString()

        {

            return width .ToString ();

        }

    }

小結:類實例_point和_point2是同一類型,他們之間共享靜態成員變量,但 類實例_point3卻是和_point、_point2完全不同的類型,所以不能和_point、 _point2共享靜態成員變量。

說明:泛型還有許多內容,像泛型委托,泛型接口,泛型方法,泛型類,泛型 約束,其實上面的都是泛型的最基本的知識,其它的應用都建立在這些基礎之上 。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved