1. 程式人生 > >對C#中的泛型的理解

對C#中的泛型的理解

泛型概念:

泛型是公共語言執行時和程式語言提供的一種機制,它支援另外1種形式的程式碼重用,也就是演算法重用.

泛型包含泛型類,泛型介面,泛型委託,泛型方法,並非只包含簡單的泛型類.在C#中,其他例如,屬性,索引器,事件,操作符方法,構造器本身不能有型別引數T.

T(型別引數),它的目的在於指明它操作的是一個未指定的資料型別,在原始碼中能夠使用資料型別的地方都可以使用它.

為什麼要使用泛型

通過使用泛型,可以極大地提高程式碼的重用度,同時還可以獲得強型別的支援,提升了應用程式的效能,避免了隱式的裝箱、拆箱,以及執行時的型別轉換錯誤。

提高程式碼複用

冒泡演算法

不用泛型的情況下,如果是整數型別排序,下面程式碼中“?“就應為int型別,但如果這時候我們有需要給byte型別排序,就要複製一遍程式碼,然後把int改為byte。這顯然不能體現程式碼的複用。

public class SortHelper {
    public void BubbleSort(?[] array) {
        int length = array.Length;
        for (int i = 0; i <= length - 2; i++) {
            for (int j = length - 1; j >= 1; j--) {
                // 對兩個元素進行交換
                if (array[j] < array[j - 1]) {
                    temp = array[j];
                    array[j] = array[j - 1];
                    array[j - 1] = temp;
                }
           }
    }
}

做網站為了提高程式碼複用,我們通常使用模板它的具體做法是:每次生成靜態頁面時,先載入模板,模板中含有一些用特殊字元標記的佔位符,然後從資料庫讀取資料,使用讀出的資料將模板中的佔位符替換掉。

將上面的方法視為一個模板,將方法所操作的型別視為一個佔位符,由於是一個佔位符,因此可以代表任何的型別,這和靜態頁面生成時模板的佔位符可以用來代表來自資料庫中的任何資料道理是一樣的。

public class SortHelper<T> {
    public void BubbleSort(T[] array){
        // 氣泡排序方法實現體
    }
}

在型別名稱的後面加了一個尖括號,使用這個尖括號來傳遞佔位符,也就是型別引數。

接下來,看一下如何使用泛型。

當需要為一個int型別的陣列排序時:

 sorter = new SortHelper<int>();
int[] array = { 8, 1, 4, 7, 3 };
sorter.BubbleSort(array);
當需要為一個byte型別的陣列排序時:
sorter = new SortHelper<byte>();
byte [] array = { 8, 1, 4, 7, 3 };
sorter.BubbleSort(array);

效能對比

拆裝箱

1.   裝箱在值型別向引用型別轉換時發生

2.   拆箱在引用型別向值型別轉換時發生

程式碼演示

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApplication1
{
    class Program
    {
        const int ListSize = 500000;
        static void Main(string[] args)
        {
            UseArrayList();
            UseGenericList();
            Console.ReadKey();
        }
        private static void UseArrayList()
        {
            ArrayList list = new ArrayList();
            long startTicks = DateTime.Now.Ticks;
            for (int i = 0; i < ListSize; i++)
            {
                list.Add(i);//i為int型別,list為引用型別, 存在一個裝箱操作
            }
            for (int i = 0; i < ListSize; i++)
            {
                int value = (int)list[i];//list[i]為引用型別,value為int型別。 進行一個拆箱操作
            }
            long endTicks = DateTime.Now.Ticks;
            Console.WriteLine("使用ArrayList,耗時:{0} ticks", endTicks - startTicks);
        }
        private static void UseGenericList()
        {
            List<int> list = new List<int>();
            long startTicks = DateTime.Now.Ticks;
            for (int i = 0; i < ListSize; i++)
            {
                list.Add(i);
            }
            for (int i = 0; i < ListSize; i++)
            {
                int value = list[i];
            }
            long endTicks = DateTime.Now.Ticks;
            Console.WriteLine("使用List<int>,耗時:{0} ticks", endTicks - startTicks);
        }
    }
}
執行效果

型別安全

ArrayList list = new ArrayList();
int i = 100;
list.Add(i);
string value = (string)list[0];

有些經驗的同學就可以看出這段程式碼有問題,因為型別不匹配,新增到ArrayList中的是一

個int型別,而獲取時卻想將它轉換為string類。但是編譯器不能識別,不管是int也好,string也好,

它們都是Object型別。在編寫程式碼時,編譯器提供給開發者的最大幫助之一就是可以檢查出錯誤,也就是常稱的編譯時錯誤(Compile time error)。當使用ArrayList時,對於上面的問題,編譯器無能為力,因為它認為其是合法的,編譯可以順利通過。這種錯誤有時候隱藏在程式中很難發現,最糟糕的情況是產品已經交付使用者,而當用戶在使用時不巧執行到這段程式碼,便會丟擲一個異常,這時的錯誤,稱為執行時錯誤(Runtime error)。

通過使用泛型集合,這種情況將不復存在,當試圖進行類似上面的轉換時,根本無法通

過編譯,這樣有助於儘早發現問題:

List<int> list = new List<int>();
int i = 100;
list.Add(i);
string value = (string)list[0];   // 編譯錯誤

通過以上這些對比,可以看出泛型給我們程式設計提供了很大的方便,當然這些只是我查到的一些資料加上自己的整理和實踐,如有不足之處請大家批評指正。


相關推薦

談談我Java理解

eg1: Map map = new HashMap(); map.put("key" , "xuqiang"); String s = (String) map.get("key"); 大家都知

關於C#參數約束(where T : class)

name ica title logic .get ted inter host ase .NET支持的類型參數約束有以下五種:where T : struct | T必須是一個結構類型where T :

c++new的理解

前幾天複習C++教程看到下面的語句 char *p=NULL;    //初始化為NULL的指標 p=new char[20];    //為變數請求記憶體 乍一看註釋,好像是正確的,但是仔細一想,又發現是有問題的 “為變數請求記憶體”

C++使用導致的膨脹問題

博主從事C++軟體開發多年,由於之前的開發環境都是資源充足的伺服器,不用考慮磁碟空間的問題。最近打算在智慧家居主機的嵌入式平臺上使用C++進行開發。FLASH儲存空間有限,這是必須要考慮的因素,一定要重視。 如下定義兩個list,元素型別不同: list&l

C#(下)

上一節介紹了泛型類和泛型方法,下面著重介紹泛型介面。 介面:表示純粹抽象的行為,不能有建構函式和欄位,成員是隱式公有的(不能使用修飾符),介面名一般以大寫字母 I 開頭。 注意:雖然介面不能例項化,但可以宣告介面型別的變數並使用實現介面的非抽象類或結構體例項化(抽象類可以使

c#的協變與逆變:詳解

in(泛型修飾符)(C# 參考) Visual Studio 2013 其他版本 0(共 1)對本文的評價是有幫助 - 評價此主題 對於泛型型別引數,in 關鍵字指定該型別引數是逆變的。 可以在泛型介面和委託中使用 in 關鍵字。

C#(上)

泛型:泛型用來實現獨立於被包含型別的功能。比如建立引數型別不同,但是功能相同的方法。 泛型的宣告: 1、一般使用 <T> 來宣告,T(可以用其他大寫字母代替) 代表要被替換的型別,可以是值型別或引用型別; 2、<T> 放在類名,方法名(方法的引數列表

C#方法與介面

http://blog.csdn.net/aladdinty/article/details/3486532 using System; using System.Collections.Generic; using System.Linq; using Sys

C#理解

泛型概念: 泛型是公共語言執行時和程式語言提供的一種機制,它支援另外1種形式的程式碼重用,也就是演算法重用. 泛型包含泛型類,泛型介面,泛型委託,泛型方法,並非只包含簡單的泛型類.在C#中,其他

JavaT和Class<T>以及Class<?>的理解(轉)

tcl ota 特定 類型 基本 ext pla enum extend 註意:class是java的關鍵字, 在聲明Java類時使用; Class類的實例表示Java應用運行時的類(class ans enum)或接口(interface and annotatio

淺析內存齊與ANSI Cstruct數據的內存布局

開發 分析 clas type spa 速度 嚴格 通過 取數據 這些問題或許對不少朋友來說還有點模糊,那麽本文就試著探究它們背後的秘密。 首先,至少有一點可以肯定,那就是ANSI C保證結構體中各字段在內存中出現的位置是隨它們的聲明順序依次遞增的,並且第一個字段的首地址等

C# 理解之大白話

泛型:泛就是多,許多,很多的意思;型:就是型別,比如:int、float、double等等的資料型別;連線起來就是許多不同的資料型別,包括內建資料型別:就是系統自帶,定義好的;自定義型別:就是自己定義的,比如說自己定義的類型別; 為什麼要用泛型? 其實在專案研發中,經常會出

C++字串常量的理解

/* 常量儲存總結:1.區域性變數儲存在棧中,棧中的記憶體隨著定義所在區間的結束自動釋放;2.new申請的記憶體在堆中,堆中記憶體需要手動free,否則它會一直存在直到程式結束;3.全域性變數、靜態變

C++類和封裝的理解

    封裝是將相對獨立,能夠廣泛使用的程式功能提煉出來,編寫成函式或類等形式的可重用程式碼。可重用的程式碼的特點是“一次開發,長期使用”。C++的封裝的語法格式用一個簡單的例子來看下class Rectangle //長方形類:宣告成員{public:double a,b;

C# 理解

泛型是 2.0 版 C# 語言和公共語言執行庫 (CLR) 中的一個非常重要的新功能。在此之前進行資料轉化時候需要進行裝箱與拆箱操作。我們知道裝箱與拆箱需要消耗很大效能,泛型的引用主要優點是效能。在學習泛型之前我們先了解一下值型別,引用型別以及裝箱,拆箱。值型別儲存在棧上,引

C++建構函式、解構函式、虛擬函式及普通成員函式的理解

這裡我們主要討論建構函式、解構函式、普通成員函式、虛擬函式,對這幾種函式說說自己的理解。 對建構函式的總結 對建構函式,我們先來看看如下的程式碼 #include <iostream> using namespace std; cla

Yii2 yiiwebUser的理解,和自建的appmodelsUser(基礎版),frontendmodelsUser的應用原理

end his iat getter authent property 用戶id tails uniq yii\web\User 是一個統稱,為用戶,沒有具體實例,只能管理; 此處以app\models\User為基準; app\models\User 是映射數據表us

Java通配符的一點概念

for name 安全 msg simple clist getc 保持 spa 以List<T>為例,通常如果我們想在List中存儲某種類型的數據,我們會用下面的語法進行聲明和使用: 1 List<String> allMsg =

C#入門集合List<T>

div nbsp 需要 強制轉換 初始 cnblogs lsi 轉換 blog 泛型集合 List<T> List<T>泛型集合特點: <T>表示泛型,T是Type簡寫,表示當前不確定具體類型; 可以根據用戶的實際需要,確定當前集合需要

面向象設計——“”的起步

rac -m sharp mil rabl dex 兩個 無法 ini 泛型是 2.0 版 C# 語言和公共語言執行庫 (CLR) 中的一個新功能。泛型將類型參數的概念引入 .NET Framework,類型參數使得設計例如以下類和方法成為可能:這些