[食譜好菜] 能不能講一下什麼是泛型(Generics)?

  • 23090
  • 0
  • C#
  • 2016-03-26

被問到「你能不能講一下什麼是 C# 中的泛型?」,這個時候我突然覺得泛型離我好遠、好遠…,明明平常用很多,常常見面啊!為什麼現在講不出來!? Orz…

原來我平常只懂得用,其實對於它的定義、限制不是很了解,稱得上是不學無術,今天被問到這個問題算是有一個機會可以讓我了解「泛型」這個好朋友,特此記錄,以示提醒。

下面是我參考的文章,大家可以直接去看這些文章的說明。

什麼是泛型?

泛型是在 C# 2.0 加進來的功能,它將型別給參數化,泛型允許我們在設計型別或是方法的時候可以先宣告一個或多個型別參數,而這個型別參數通常用 T 或 T1、T2…來代表,下面的例子就是一個泛型型別 Country<T>

public class Country<T>
{
    public string GetCountryName()
    {
        return typeof(T).Name;
    }
}

在 Country 這個型別裡面有一個 GetCountryName() 方法來取得傳遞進來的型別參數的型別名稱,我們可以看到下圖,我傳入 Taiwan 這個型別,呼叫 GetCountryName() 來取得 CountryName,得到的就是 Taiwan。

泛型用在方法就叫泛型方法,下面我就將 GetCountryName() 改成泛型方法 GetCountryName<T>()

public static class Country
{
    public static string GetCountryName<T>(this T me)
    {
        return me.GetType().Name;
    }
}

一樣我傳入 Taiwan 這個型別,取得型別名稱依舊是 Taiwan。

泛型在其他程式語言有被稱為「模板」,也有被稱為「參數多型」,泛型讓我們設計出使不同型別藉由套板之後,可以執行相同的行為,在 C# 中最常使用的泛型型別之一就是 List<T>,相信大家對這個型別應該不陌生。

為什麼需要泛型?

在 C# 1.0/1.1 的時候是還沒有泛型功能的,當然也沒有 List<T> 這種東西可以用的,如果要建立一個任意型別的集合要怎麼辦?這時候就可以用 ArrayList

可以看到 ArrayList.Add() 這個方法裡面要給的值的型別是 object,也就是說 ArrayList 裡面我們可以塞入任何繼承自 object 這個型別的任何物件。

哇塞!這多恐怖啊!

我們的 ArrayList 裡面第 1 個元素是 Order,第 2 個有可能是 OrderDetail,第 3 個又變成 Customer,每個元素的實際型別都不一樣,而且即使我們知道每個元素的實際型別,我們要對元素進行操作還得經過轉型,當然轉型沒有什麼不好,但是當有大量轉型的時候,就會影響到效能。

因此,泛型就在 C# 2.0 的時候誕生了,以集合來說,藉由明確指定集合是屬於哪一種型別,來確保在編譯期間集合內元素的實際型別與傳入的型別參數是相符的,除此之外還減少在 runtime 時期轉型所消耗的效能,還能讓其他人明確地知道集合是屬於哪一種型別,可說是一舉多得。

泛型很方便使用,我經常使用但是了解的太少,這次算是對泛型有了更加深入的了解,過去不求甚解,累積了一堆學習債,這些在未來都要一點一滴慢慢還。

相關資源

C# 指南
ASP.NET 教學
ASP.NET MVC 指引
Azure SQL Database 教學
SQL Server 教學
Xamarin.Forms 教學