iT邦幫忙

2025 iThome 鐵人賽

DAY 13
0

前言

在學習了類別、繼承、多型之後,今天要來學習 C# 中一個非常實用的進階工具:泛型 (Generics)。泛型的主要目的就是:避免重複撰寫相同邏輯的程式碼,增加型別安全 (type safety),避免因為型別轉換造成錯誤,提升效能,因為泛型不需要使用 object 來裝載所有資料。在 C# 的世界中,像是 List<T>Dictionary<TKey, TValue> 等集合類別,都是泛型最經典的應用。


先來看一個簡單的泛型例子:

// Declare the generic class.
public class GenericList<T>
{
    public void Add(T item) { }
}

public class ExampleClass { }

class TestGenericList
{
    static void Main()
    {
        // Create a list of type int.
        GenericList<int> list1 = new();
        list1.Add(1);

        // Create a list of type string.
        GenericList<string> list2 = new();
        list2.Add("");

        // Create a list of type ExampleClass.
        GenericList<ExampleClass> list3 = new();
        list3.Add(new ExampleClass());
    }
}

在一開頭的:

public class GenericList<T>
{
    public void Add(T item) { }
}

是一個泛型類別,<T> 表示類型參數,T 是一個佔位符,可以在類別內部當作類型使用。Add
方法接受一個類型為 T 的參數。
在這個例子中:GenericList創建了一個只能存儲整數的列表。GenericList創建了一個只能存儲字串的列表。GenericList創建了一個只能存儲 ExampleClass實例的列表。


泛型類別與方法結合了可重用性、型別安全性以及效能,這些是非泛型類別與方法所無法同時兼顧的。泛型型別參數會在編譯時期被實際的型別引數取代。在前面的範例中,編譯器會將 T 替換為 int。泛型最常被用於集合 (collections) 以及操作集合的方法。接著看下方的範例程式碼:

// Type parameter T in angle brackets.
public class GenericList<T>
{
    // The nested class is also generic, and
    // holds a data item of type T.
    private class Node(T t)
    {
        // T as property type.
        public T Data { get; set; } = t;

        public Node? Next { get; set; }
    }

    // First item in the linked list
    private Node? head;

    // T as parameter type.
    public void AddHead(T t)
    {
        Node n = new(t);
        n.Next = head;
        head = n;
    }

    // T in method return type.
    public IEnumerator<T> GetEnumerator()
    {
        Node? current = head;

        while (current is not null)
        {
            yield return current.Data;
            current = current.Next;
        }
    }
}
class Program
{
    static void Main()
    {
        // A generic list of int.
        GenericList<int> list = new();

        // Add ten int values.
        for (int x = 0; x < 10; x++)
        {
            list.AddHead(x);
        }

        // Write them to the console.
        foreach (int i in list)
        {
            Console.WriteLine(i);
        }

        Console.WriteLine("Done");
    }
}

結果:
https://ithelp.ithome.com.tw/upload/images/20250925/20178767V77Elng3Nh.png
T 可用於巢狀的 Node 類別。當 GenericList<T> 使用特定類型(例如 GenericList<int>)實例化時,每個出現的 T 都會被替換為 int。然後可以看到在Main當中的使用端程式碼如何使用泛型 GenericList<T> 類別建立整數清單。如果更改類型參數,在Main裡面將建立字串或任何其他自訂類型的清單。


Generics overview

  • 使用泛型型別可以最大化程式碼的重用性、型別安全性以及效能。
  • 泛型最常見的用途是建立集合類別。
  • 在 .NET 類別庫中,System.Collections.Generic 命名空間包含了多個泛型集合類別。建議盡可能使用泛型集合,而不要使用 System.Collections 命名空間中的 ArrayList 這類類別。
  • 你也可以自行建立泛型的介面、類別、方法、事件與委派。
  • 泛型類別可以設定限制條件 (constraints),以便能夠存取特定資料型別的方法。
  • 你也可以透過反射 (reflection) 在執行階段取得泛型資料型別中實際使用的型別資訊。

上一篇
Day12-介面與抽象類別
下一篇
Day14-集合 (Collections)
系列文
30 天從 Python 轉職場 C# 新手入門14
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言