從裝箱拆箱看泛型

2022-03-14 06:25:30 字數 4140 閱讀 2786

.net很容易把值型別轉換為引用型別,所以可以在需要物件的任意地方使用值型別。例如int可以賦予乙個物件,從值型別轉換為引用型別稱為裝箱。如果方法需要把乙個物件作為引數,同時傳遞乙個值型別,裝箱操作就會自動進行。另一方面,裝箱的值型別可以使用拆箱操作轉換為值型別。

定義乙個一般的、非泛型的簡化鍊錶類,它可以包含任意型別的物件,在鍊錶中,乙個元素引用下乙個元素。所以必須建立乙個類,它將物件封裝在鍊錶中,並引用下乙個物件。類linkedlistnode包含乙個屬性value,該屬性用建構函式初始化。另外linkedlistnode類包含對鍊錶中下乙個元素和上乙個元素的引用,這些元素都可以從屬性中訪問。

先定義linkedlistnode類

public

class

linkedlistnode

public

object value

public linkedlistnode next

public linkedlistnode prev

}

再定義乙個非泛型的簡化鍊錶類,實現非泛型介面

public

class

linkedlist : ienumerable

public linkedlistnode last

public linkedlistnode addlast(object

node)

else

return

newnode;

}public

ienumerator getenumerator()}}

用ilspy檢視il**

il_0000: nop

il_0001: newobj instance

void

praticecharter01.linkedlist::.ctor()

il_0006: stloc.

0il_0007: ldloc.

0il_0008: ldc.i4.

3il_0009: box [mscorlib]system.int32

il_000e: callvirt instance

class praticecharter01.linkedlistnode praticecharter01.linkedlist::addlast(object

) il_0013: pop

il_0014: ldloc.

0il_0015: ldc.i4.

4il_0016: box [mscorlib]system.int32

il_001b: callvirt instance

class praticecharter01.linkedlistnode praticecharter01.linkedlist::addlast(object

) il_0020: pop

il_0021: nop

il_0022: ldloc.

0il_0023: callvirt instance

class

[mscorlib]system.collections.ienumerator praticecharter01.linkedlist::getenumerator()

il_0028: stloc.1.

try

//end .try

分析il**可知上述過程發生了兩次裝箱和兩次拆箱,在foreach語句中,鍊錶中的元素被強制轉換為整形,裝箱和拆箱操作很容易使用,但效能損失比較大,泛型能很好的避免拆裝箱,從而提供效能。

再定義乙個泛型版本,該泛型集合實現泛型介面ienumerator

public

class linkedlistnode

public t value

public linkedlistnodenext

public linkedlistnodeprev

}public

class linkedlist: ienumerable

public linkedlistnodelast

public linkedlistnodeaddlast(t node)

else

return

newnode;

}public ienumeratorgetenumerator()

}ienumerator ienumerable.getenumerator()

}

static

void main(string

args)

檢視il**

il_0000: nop

il_0001: newobj instance

void

class praticecharter01.linkedlist`1

::.ctor()

il_0006: stloc.

0il_0007: ldloc.

0il_0008: ldc.i4.

3il_0009: callvirt instance

class praticecharter01.linkedlistnode`1

0> class praticecharter01.linkedlist`1

::addlast(!0

) il_000e: pop

il_000f: ldloc.

0il_0010: ldc.i4.

4il_0011: callvirt instance

class praticecharter01.linkedlistnode`1

0> class praticecharter01.linkedlist`1

::addlast(!0

) il_0016: pop

il_0017: nop

il_0018: ldloc.

0il_0019: callvirt instance

class [mscorlib]system.collections.generic.ienumerator`1

0> class praticecharter01.linkedlist`1

::getenumerator()

il_001e: stloc.1.

try

//end .try

il code

發現並沒拆裝箱過程,說明泛型能提供型別安全的類並能提**用程式的效能,基於以上幾點在訪問資料層經常使用泛型以期提高**的重用性,在資料訪問泛型類通常需要呼叫泛型型別中的方法,所以必須給泛型類新增約束,泛型支援幾種約束如下:

(1)where t:struct 對於結構約束,型別t必須是值型別

(2)where t:class 類約束指定型別t必須是引用型別

(3)where t:ifoo指定型別t必須實現介面ifoo

(4)where t:new()這是乙個建構函式約束,指定型別t必須有乙個預設建構函式

(5)where t1:t2這個約束也可以指定,型別t1派生自泛型型別t2、該約束稱為裸約束

定義乙個實現icomparable泛型介面的實體

public

class employemodel:icomparable

public

string lastname

public

int age

public

intcompareto(employemodel other)

}

定義泛型類,該泛型有兩個約束

public

class basedalwhere t : class,icomparable

class

program

}public

struct

nullablestruct

public

class

student

public

string lastname

public

int age

}

總結泛型類可以建立獨立於型別的類,泛型方法是獨立於型別的方法,介面結構和委託也可以用泛型的方式建立。

C 裝箱 拆箱 泛型

1 裝箱 值型別轉引用型別。開闢一塊記憶體空間進行存放資料。2 拆箱 引用型別轉值型別。值型別存放在棧上,引用型別存放在堆上。裝箱需要消耗記憶體,所以引出了泛型。泛型 1.使用非泛型集合時引發的裝箱和拆箱操作 看下面的一段 1 2 3 4 5 6 7 8 vararray newarraylist ...

java學習 裝箱與拆箱 泛型

把基本資料型別賦給對應的包裝類。比如 把int賦值給integer,對他的操作就需要用它的方法了。是值型別轉換為引用型別的過程。把乙個包裝類賦給基本資料型別。由引用型別轉換為值型別的過程。integer i 1 裝箱 int j i 拆箱 典型應用 list list new arraylist l...

C 委託 泛型 事件 裝箱拆箱

一 委託 我感覺的委託就是指乙個函式指標,指向被委託的方法,在定義的時候把返回值型別與引數全部定義好,建立的例項相當於乙個指向被委託函式的指標,然後將需要的資料通過委託傳進去 是先呼叫委託例項,然後委託例項再呼叫方法 簡寫的那種方式更能體現它像乙個函式指標 注意 多播委託就是用 與 進行操作 當多播...