Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> C#

Giải thích cách Generics hoạt động trong C#

Generics được thêm từ C# 2.0, là khái niệm quan trọng nhất. Cho phép viết code tái sử dụng, hiệu năng cao, type-safe tại compile-time. Dùng kiểu trong code mà không cần biết trước kiểu đó.

Generics dùng nhiều nơi trong .NET: collections, delegates, async code. Không cần biết size collection trước, dùng được với mọi kiểu element, kể cả custom type. C# hỗ trợ generic types (class, interface...) và generic methods.

Trong generics có type parameters và type arguments, tương tự method có parameters và arguments.

Generic Types

Cú pháp: type parameters trong ngoặc nhọn sau tên kiểu. Ví dụ Locator<T>:

public class Locator<T> { }

Tạo instance: thay T bằng kiểu thực:

var stringLocator = new Locator<string>();

Dùng type parameter trong method class:


public class Locator<T>
{
    public IList<T> Items { get; set; }
    public T Locate(int index) => Items[index];
}

var stringLocator = new Locator<string>();
string item = stringLocator.Locate(2);

Lợi ích: IntelliSense hiểu kiểu thực. stringLocator.Locate(4) trả về string chứ không phải T. Gán cho kiểu khác (như int) → lỗi compile.

Generic type có thể dùng type parameter làm type argument khi kế thừa base generic hoặc implement interface generic. LinkedList<T> implement IEnumerable<T>.

Generic Methods

Method khai báo type parameter dùng trong method, làm tham số và kiểu trả về. Ví dụ Swap<T>:


public class Swapper
{
    public T Swap<T>(ref T first, ref T second)
    {
        T temp = first;
        first = second;
        second = temp;
        return temp;
    }
}

var swapper = new Swapper();
int a = 5, b = 3;
int result = swapper.Swap<int>(ref a, ref b);
// a=3, b=5

Có thể nhiều generic parameters. Dictionary<TKey, TValue> có 2 tham số.

Điều gì có thể là Generic?

Kiểu (trừ enum): class, struct, interface, delegate.

Member của kiểu: chỉ method và nested type. KHÔNG thể generic: field, property, indexer, constructor, event, finalizer.

Ví dụ hoàn chỉnh

using System;
using System.Collections.Generic;

class Program
{
    static void Main()
    {
        var stringLocator = new Locator<string>()
        {
            Items = new string[] { "JavaScript", "CSharp", "Golang" }
        };
        string item = stringLocator.Locate(1);
        Console.WriteLine(item); // CSharp

        var swapper = new Swapper();
        int a = 5, b = 3;
        int result = swapper.Swap<int>(ref a, ref b);
        Console.WriteLine($"a = {a}, b = {b}"); // a=3, b=5
    }
}

public class Locator<T>
{
    public IList<T> Items { get; set; }
    public T Locate(int index) => Items[index];
}

public class Swapper
{
    public T Swap<T>(ref T first, ref T second)
    {
        T temp = first;
        first = second;
        second = temp;
        return temp;
    }
}

Kết quả đầu ra

CSharp
a = 3, b = 5