C#筆記(一):類型,泛型,集合


最近在學習.NET Framework 高級編程這本書,感覺挺有意思的,於是根據自己的理解,做了筆記,總結下內容。本文筆記主要是從.NET類型,泛型,集合這三個方面進行描述。

本文內容:

  1. 類型

  2. 泛型

  3. 集合

 


 

1.類型

類型是對程序要處理的數據對象的分類。不同的數據對象占用存儲空間不同,操作處理方法不同,所以必須分門別類;

(1)C#的主要類型有:

基本類型:數值、字符、邏輯型、字符串、對象(object)

系統或自定義的類型:結構、枚舉、類等等。

上述這些類型,所占的內存空間不同。有的類型占用內存空間是確定的,有的不確定。

根據它們被分配存儲空間方式的不同,可以分為:值類型/引用類型兩大類。

上述的類型中,你是否又能區分它們屬於哪一類呢?

基本數據類型大部分是值類型,除了object, string屬於引用類型;類是引用類型;結構和枚舉是值類型。

(2)內存的使用分別:棧(stack), 堆(heap) 靜態區(static)。

 

值類型直接分配在棧上;

引用類型包括兩部分:對象的引用(地址)在棧(stack)上,對象本身在堆(heap)上。

靜態區(static)存放的是與對象的實例無關的部分。即當程序一裝入內存,就要分配好。

如:入口方法,構造方法,常量,其他用static修飾的成員。

(3)舉例:

例一:

int x, y=0;
x = y;
y = 9;

 

例二:設有類Myobj定義為:

class Myobj

{

public int age;

public string name;

}

Myobj a, b;

a = new Myobj();

a.age = 28; a.name = "puppy";

b = a;

a.age = 18; a.name = "doggy";

Console.WriteLine(b.age);

Console.WriteLine(b.name);

 

例三:

string x, y="string1";

x = y;

y = "string2";

Console.WriteLine(x);

 

第一個例子輸出是0。當y=9時,實際上是在棧中重新分配一個內存地址。

第二個例子輸出是18和doggy。b=a時,a和b同時指向一個地址空間

第三個例子輸出是string1。string是一個特殊的引用類型。 string實例在內存中不可修改。當需要修改時,總是創建一個新的實例,並將變量指向新的實例。

(在程序中頻繁修改字符串變量,會產生大量內存垃圾。這是我們要使用StringBuilder類的原因)

 

(4)裝箱和拆箱

裝箱:將值類型轉換為引用類型,按照自己的理解來說在堆中生成一個新的對象,棧中原本的地址指向該對象。

拆箱:將引用類型轉換為值類型,大致同上,過程相反。

int x=1;

Object y=x;//裝箱

int z=(int)y;/拆箱

 

2.泛型

問題的緣起:

請看一個Stack的程序。Stack是一種數據結構。可以存放許多元素,遵循后進先出的原則。

舉例:(Stack)

class StackOfInt {

private int[] m_ItemArray;

private int m_Index = 0;

public const int Max_Size = 100;

public StackOfInt () { m_ItemArray = new int[Max_Size]; }

public int Pop() {

if (m_Index == 0)

throw new System.InvalidOperationException("Can't

Pop an empty stack.");

return m_ItemArray[--m_Index];

}

public void Push(int item){

if (m_Index == Max_Size)

throw new System.InvalidOperationException("Can't

push an item on a full stack.");

m_ItemArray[m_Index++] = item;

}

}

 

缺點:這樣的棧用object類型作為元素類型,可以供所有類型使用

但在壓入元素時,要裝箱;取用元素時要拆箱,代價很大,執行效率低;

類型不安全。轉換類型時容易出錯。

解決方案:如果我們可以在Stack類的定義中,提供一個類作參數,則可以簡化此問題的解決。泛型的定義:在定義一個類型時,使用另一個或幾個類型為參數,類型參數用<>圍住,放在所定義的類型名后面。

在使用帶有類型參數的泛型類型時,同時要給定參數類型的具體類型。

舉例:定義泛型Stack類

class Stack<T> {

private T[] m_ItemArray;

private int m_Index = 0;

public const int Max_Size = 100;

public Stack() { m_ItemArray = new T[Max_Size]; }

public T Pop() {

if (m_Index == 0)

throw new System.InvalidOperationException("Can't

Pop an empty stack.");

return m_ItemArray[--m_Index];

}

public void Push(T item){

if (m_Index == Max_Size)

throw new System.InvalidOperationException("Can't

push an item on a full stack.");

m_ItemArray[m_Index++] = item;

}

}

 

泛型的優點:

讓代碼更具有通用性,更簡潔;

強類型,類型安全,不用擔心類型轉換錯;

不用浪費很多裝箱、拆箱的時間。

3.集合

集合類型是其對象中包含多個其他對象的特殊類型。

數組是最常用的集合類型。

要進一步理解的是,當我們在程序中申明一個數組時,實際上是指示CLR在執行期間幫我們創建和管理一個集合類型;

該集合類型的基類為System.Array

所以,我們可以對數組使用一些固有的屬性和方法,如Length,Rank,Copy,Clone。他們來自Array類;還可以對數組用foreach來遍歷。這是因為Array已經實現IEnumerable 接口。

由此我們可以牢記,數組是引用類型。可以用數組作為方法的參數,不使用ref也可以從方法中傳出修改的結果

舉例:

using System.Collection.Generic;

public class Program {

public static void Main() {

List<int> list = new List<int>(3);

for (int i=0; i<8; i++) {

list.Add(i);

System.Console.WriteLine(“Count: {0} Capacity: {1}”,

list.Count, list.Capacity);

}

list.TrimExcess();

System.Console.WriteLine(“Count: {0} Capacity: {1}”,

list.Count, list.Capacity );

}

}

 

作者: ForEvErNoME
出處: http://www.cnblogs.com/ForEvErNoME/
歡迎轉載或分享,但請務必聲明文章出處。如果文章對您有幫助,希望你能 推薦關注
 
 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM