跳過到頁腳內容
.NET幫助

C# 泛型(對於開發者的運行原理)

C# 泛型引入了一種設計類別、方法、介面、和委派的方法,其管理的資料型別可以指定為參數。 這個概念被稱為泛型型別參數,允許創建靈活且可重用的代碼組件。 通過使用泛型,您可以最大化代碼的重用性、型別安全性和性能。 例如,一個泛型類別可以定義一次,但可以使用各種資料型別進行實例化,提供多樣性和型別的完整性。 在本文中,我們將了解 C# 泛型的基礎知識以及IronPDF 庫的 PDF 操作功能

泛型類別的基礎

C# 中的泛型類別是一個用於創建包含或操作的型別佔位符的類別的藍圖。 這個佔位符通常由T表示,代表一個型別參數,當類別被實例化時被指定。 我們可以創建具有型別參數T的泛型類別來處理各種資料型別。泛型類別特別適用於集合類別,如列表、隊列和哈希表,因為它們可以容納任何資料型別,同時保證型別安全並減少轉型的需求。

泛型類別的簡單例子

考慮一個名為 Box 的泛型類別,設計用來儲存任何型別的值:

public class Box<T>
{
    private T data;

    public Box(T data)
    {
        this.data = data;
    }

    public T Data
    {
        get { return data; }
    }
}
public class Box<T>
{
    private T data;

    public Box(T data)
    {
        this.data = data;
    }

    public T Data
    {
        get { return data; }
    }
}
Public Class Box(Of T)
'INSTANT VB NOTE: The field data was renamed since Visual Basic does not allow fields to have the same name as other class members:
	Private data_Conflict As T

	Public Sub New(ByVal data As T)
		Me.data_Conflict = data
	End Sub

	Public ReadOnly Property Data() As T
		Get
			Return data_Conflict
		End Get
	End Property
End Class
$vbLabelText   $csharpLabel

要使用此類,您需要創建一個實例,指定T的實際型別:

Box<int> integerBox = new Box<int>(123);
Box<string> stringBox = new Box<string>("Hello");
Box<int> integerBox = new Box<int>(123);
Box<string> stringBox = new Box<string>("Hello");
Dim integerBox As New Box(Of Integer)(123)
Dim stringBox As New Box(Of String)("Hello")
$vbLabelText   $csharpLabel

這段代碼說明了一個單一類別(Box)如何適應以儲存不同的資料型別(intstring),展示了泛型在代碼重用和型別安全中的力量。

實施泛型方法

泛型方法類似於泛型類別,但在方法層次定義型別參數。 這允許創建可以操作不同型別的方法,而將其定義在非泛型或泛型類別中。

泛型方法的例子

以下是一種方法,可以交換任何型別的陣列中的兩個元素:

public class Utility
{
    // Swaps two elements by reference using generics
    public static void Swap<T>(ref T lhs, ref T rhs)
    {
        T temp = lhs; // Store lhs in a temporary variable
        lhs = rhs;    // Assign rhs to lhs
        rhs = temp;   // Assign temp (original lhs) to rhs
    }
}
public class Utility
{
    // Swaps two elements by reference using generics
    public static void Swap<T>(ref T lhs, ref T rhs)
    {
        T temp = lhs; // Store lhs in a temporary variable
        lhs = rhs;    // Assign rhs to lhs
        rhs = temp;   // Assign temp (original lhs) to rhs
    }
}
Public Class Utility
	' Swaps two elements by reference using generics
	Public Shared Sub Swap(Of T)(ByRef lhs As T, ByRef rhs As T)
		Dim temp As T = lhs ' Store lhs in a temporary variable
		lhs = rhs ' Assign rhs to lhs
		rhs = temp ' Assign temp (original lhs) to rhs
	End Sub
End Class
$vbLabelText   $csharpLabel

上述方法的使用範例如下:

int a = 1, b = 2;
Utility.Swap<int>(ref a, ref b);

string first = "world", second = "hello";
Utility.Swap(ref first, ref second);
int a = 1, b = 2;
Utility.Swap<int>(ref a, ref b);

string first = "world", second = "hello";
Utility.Swap(ref first, ref second);
Dim a As Integer = 1, b As Integer = 2
Utility.Swap(Of Integer)(a, b)

Dim first As String = "world", second As String = "hello"
Utility.Swap(first, second)
$vbLabelText   $csharpLabel

探索泛型介面和委派

泛型介面和委派使得能定義可以操作任何型別的合約和回調方法。 在類別或方法中實施泛型介面或使用泛型委派可以提高靈活性和代碼重用。

泛型介面的例子

一個用於數據訪問操作的泛型儲存庫介面可能看起來像這樣:

public interface IRepository<T>
{
    void Add(T item);
    T GetById(int id);
    IEnumerable<T> GetAll();
}
public interface IRepository<T>
{
    void Add(T item);
    T GetById(int id);
    IEnumerable<T> GetAll();
}
Public Interface IRepository(Of T)
	Sub Add(ByVal item As T)
	Function GetById(ByVal id As Integer) As T
	Function GetAll() As IEnumerable(Of T)
End Interface
$vbLabelText   $csharpLabel

這個介面可以由任何類別實作以處理特定的資料型別,允許在不同型別之間具有一致的數據訪問模式。

泛型委派的例子

泛型委派可用於定義型別安全的回調:

public delegate void Action<T>(T item);
public delegate void Action<T>(T item);
Public Delegate Sub Action(Of T)(ByVal item As T)
$vbLabelText   $csharpLabel

運用泛型集合

泛型集合類別,如 ListDictionary<TKey, TValue>System.Collections.Generic 命名空間中的其他類別,為任何特定型別的資料的存儲和操作提供型別安全、高效的集合。 這些集合優於非泛型的對應集合,因為它們消除了轉型的需要並減少了運行時錯誤。

List<string> names = new List<string>();
names.Add("Alice");
names.Add("Bob");

Dictionary<int, string> keyValuePairs = new Dictionary<int, string>();
keyValuePairs.Add(1, "One");
keyValuePairs.Add(2, "Two");
List<string> names = new List<string>();
names.Add("Alice");
names.Add("Bob");

Dictionary<int, string> keyValuePairs = new Dictionary<int, string>();
keyValuePairs.Add(1, "One");
keyValuePairs.Add(2, "Two");
Dim names As New List(Of String)()
names.Add("Alice")
names.Add("Bob")

Dim keyValuePairs As New Dictionary(Of Integer, String)()
keyValuePairs.Add(1, "One")
keyValuePairs.Add(2, "Two")
$vbLabelText   $csharpLabel

創建自定義泛型型別

除了使用內置泛型型別外,您還可以創建自己的泛型型別以封裝在不同的資料型別之間共同的操作,但需要以特定型別進行處理。 這種方法特別適用於建立庫、框架或工具,這些工具需要與多種資料型別一起使用。

自定義泛型型別的例子

考慮一個泛型 Result 類別,它封裝操作結果以及成功旗標和可選訊息:

public class Result<T>
{
    public bool Success { get; private set; }
    public T Data { get; private set; }
    public string Message { get; private set; }

    public Result(bool success, T data, string message = "")
    {
        Success = success;
        Data = data;
        Message = message;
    }
}
public class Result<T>
{
    public bool Success { get; private set; }
    public T Data { get; private set; }
    public string Message { get; private set; }

    public Result(bool success, T data, string message = "")
    {
        Success = success;
        Data = data;
        Message = message;
    }
}
Public Class Result(Of T)
	Private privateSuccess As Boolean
	Public Property Success() As Boolean
		Get
			Return privateSuccess
		End Get
		Private Set(ByVal value As Boolean)
			privateSuccess = value
		End Set
	End Property
	Private privateData As T
	Public Property Data() As T
		Get
			Return privateData
		End Get
		Private Set(ByVal value As T)
			privateData = value
		End Set
	End Property
	Private privateMessage As String
	Public Property Message() As String
		Get
			Return privateMessage
		End Get
		Private Set(ByVal value As String)
			privateMessage = value
		End Set
	End Property

	Public Sub New(ByVal success As Boolean, ByVal data As T, Optional ByVal message As String = "")
		Me.Success = success
		Me.Data = data
		Me.Message = message
	End Sub
End Class
$vbLabelText   $csharpLabel

IronPDF:C# PDF 庫

IronPDF 是為 .NET 開發人員設計的綜合庫,用於在其應用程序中創建、編輯和提取 PDF 文件。 IronPDF 幫助從 HTML 生成 PDF,編輯現有的 PDF,將 PDF 轉換為圖像,還有許多其他功能。 雖然 IronPDF 本身並不是基於泛型,但了解如何在 C# 環境中使用這個庫可以大大提升您的應用程序的文件管理能力。

代碼示例:與 IronPDF 一起使用 virtual 關鍵字

在這裡使用泛型的想法是創建一個可重用的方法,能夠從任何給定的 HTML 字符串生成 PDF。 這個方法將是泛型的,允許我們根據需要指定不同型別的元數據或配置。

首先,讓我們定義一個簡單的泛型類,其中將包含我們的 PDF 生成選項。 出於演示目的,這個類將是基本的,但您可以擴展它以適合您的需求,添加更多屬性。

public class PdfOptions<T>
{
    public T Metadata { get; set; }
    public string HtmlContent { get; set; }
}
public class PdfOptions<T>
{
    public T Metadata { get; set; }
    public string HtmlContent { get; set; }
}
Public Class PdfOptions(Of T)
	Public Property Metadata() As T
	Public Property HtmlContent() As String
End Class
$vbLabelText   $csharpLabel

現在,讓我們創建一個靜態方法,使用 IronPDF 生成 PDF,利用我們的 PdfOptions 類。 該方法將以 PdfOptions 的一個實例作為其參數,展示泛型的使用方式。

using IronPdf; // Make sure to include the necessary namespace for IronPDF

public static class PdfGenerator
{
    // Generates a PDF from provided HTML content and options
    public static void GeneratePdf<T>(PdfOptions<T> options)
    {
        // Initialize the IronPDF HtmlToPdf renderer
        var renderer = new ChromePdfRenderer();

        // Optional: Apply any renderer options here, for example, setting the paper size
        renderer.RenderingOptions.PaperSize = IronPdf.Rendering.PdfPaperSize.A4;

        // Generate the PDF from HTML content
        var pdfDocument = renderer.RenderHtmlAsPdf(options.HtmlContent);

        // Optional: Here, you can use options.Metadata in some way, depending on your generic type T
        // For simplicity, we're just printing the metadata to console if it's of type string
        if (options.Metadata is string metadataString)
        {
            Console.WriteLine($"Metadata: {metadataString}");
        }

        // Save the PDF to a file
        var fileName = $"GeneratedPdf_{DateTime.Now.Ticks}.pdf";
        pdfDocument.SaveAs(fileName);
        Console.WriteLine($"PDF generated and saved as {fileName}");
    }
}
using IronPdf; // Make sure to include the necessary namespace for IronPDF

public static class PdfGenerator
{
    // Generates a PDF from provided HTML content and options
    public static void GeneratePdf<T>(PdfOptions<T> options)
    {
        // Initialize the IronPDF HtmlToPdf renderer
        var renderer = new ChromePdfRenderer();

        // Optional: Apply any renderer options here, for example, setting the paper size
        renderer.RenderingOptions.PaperSize = IronPdf.Rendering.PdfPaperSize.A4;

        // Generate the PDF from HTML content
        var pdfDocument = renderer.RenderHtmlAsPdf(options.HtmlContent);

        // Optional: Here, you can use options.Metadata in some way, depending on your generic type T
        // For simplicity, we're just printing the metadata to console if it's of type string
        if (options.Metadata is string metadataString)
        {
            Console.WriteLine($"Metadata: {metadataString}");
        }

        // Save the PDF to a file
        var fileName = $"GeneratedPdf_{DateTime.Now.Ticks}.pdf";
        pdfDocument.SaveAs(fileName);
        Console.WriteLine($"PDF generated and saved as {fileName}");
    }
}
Imports IronPdf ' Make sure to include the necessary namespace for IronPDF

Public Module PdfGenerator
	' Generates a PDF from provided HTML content and options
	Public Sub GeneratePdf(Of T)(ByVal options As PdfOptions(Of T))
		' Initialize the IronPDF HtmlToPdf renderer
		Dim renderer = New ChromePdfRenderer()

		' Optional: Apply any renderer options here, for example, setting the paper size
		renderer.RenderingOptions.PaperSize = IronPdf.Rendering.PdfPaperSize.A4

		' Generate the PDF from HTML content
		Dim pdfDocument = renderer.RenderHtmlAsPdf(options.HtmlContent)

		' Optional: Here, you can use options.Metadata in some way, depending on your generic type T
		' For simplicity, we're just printing the metadata to console if it's of type string
		Dim tempVar As Boolean = TypeOf options.Metadata Is String
		Dim metadataString As String = If(tempVar, CStr(options.Metadata), Nothing)
		If tempVar Then
			Console.WriteLine($"Metadata: {metadataString}")
		End If

		' Save the PDF to a file
		Dim fileName = $"GeneratedPdf_{DateTime.Now.Ticks}.pdf"
		pdfDocument.SaveAs(fileName)
		Console.WriteLine($"PDF generated and saved as {fileName}")
	End Sub
End Module
$vbLabelText   $csharpLabel

最後,我們用 PdfGenerator 類來生成 PDF 文件。 在例子中,Metadata 屬性可以是一個包含標題或任何其他您認為相關的信息的字符串。

class Program
{
    static void Main(string[] args)
    {
        // Set the license key for IronPDF if needed
        License.LicenseKey = "Your-License-Key-Here";

        // Create PDF options with HTML content and metadata
        var options = new PdfOptions<string>
        {
            HtmlContent = "<h1>Hello, World!</h1><p>This is a test PDF document generated from HTML.</p>",
            Metadata = "Test PDF Title"
        };

        // Generate the PDF using the specified options
        PdfGenerator.GeneratePdf(options);
    }
}
class Program
{
    static void Main(string[] args)
    {
        // Set the license key for IronPDF if needed
        License.LicenseKey = "Your-License-Key-Here";

        // Create PDF options with HTML content and metadata
        var options = new PdfOptions<string>
        {
            HtmlContent = "<h1>Hello, World!</h1><p>This is a test PDF document generated from HTML.</p>",
            Metadata = "Test PDF Title"
        };

        // Generate the PDF using the specified options
        PdfGenerator.GeneratePdf(options);
    }
}
Friend Class Program
	Shared Sub Main(ByVal args() As String)
		' Set the license key for IronPDF if needed
		License.LicenseKey = "Your-License-Key-Here"

		' Create PDF options with HTML content and metadata
		Dim options = New PdfOptions(Of String) With {
			.HtmlContent = "<h1>Hello, World!</h1><p>This is a test PDF document generated from HTML.</p>",
			.Metadata = "Test PDF Title"
		}

		' Generate the PDF using the specified options
		PdfGenerator.GeneratePdf(options)
	End Sub
End Class
$vbLabelText   $csharpLabel

此示例說明了如何將 IronPDF 與 C# 泛型集成,提供了一種靈活的方式從 HTML 內容生成 PDF,同時允許通過泛型 PdfOptions 類進行自定義的元數據或配置。 您可以在此基礎上進行擴展,根據您的應用需要添加更加複雜的選項和渲染器配置。

C# Generics(對開發人員的工作原理):圖 1 - 使用 IronPDF 從 HTML 字符串創建 PDF 文件的泛型示例代碼輸出

結論

C# Generics(對開發人員的工作原理):圖 2 - IronPDF 許可證頁面

C# 泛型是一個強大的工具,用於開發高質量、可重用和型別安全的代碼。 通過了解和應用泛型類別、方法、介面和委派,您可以編寫更具適應性和更易於維護的代碼。 泛型不僅支持不同資料型別的代碼重用,而且保證編譯時的型別檢查,這減少了運行時錯誤並改進了整體的代碼品質。 IronPDF 提供PDF 庫工具的免費試用版,價格從$799開始。

常見問題解答

什麼是 C# 中的泛型?

C# 泛型引入了一種通過類型參數設計類別、方法、接口和委託的方法。這允許創建提供類型安全性和性能改進的靈活且可重用的代碼組件。

泛型類別在 C# 中如何運作?

C# 中的泛型類別使用類型參數,通常標記為 T,作為它所包含或運行的類型的佔位符。這允許類別在保持類型安全性的同時用各種數據類型實例化。

您能給出一個 C# 泛型類的例子嗎?

是的,一個簡單的例子是 Box 類,用於存儲任何類型的值。您可以像 BoxBox 這樣創建實例,以便使用相同的類存儲不同的數據類型。

什麼是 C# 中的泛型方法?

泛型方法在方法層中定義類型參數,允許它操作不同的類型。它可以是非泛型類或泛型類的一部分,使方法設計更具靈活性。

在 C# 中如何使用泛型接口和委託?

泛型接口和委託允許定義可以用任何類型運行的合約和回調方法,增強了靈活性和代碼重用性。

在 C# 中使用泛型集合有哪些好處?

ListDictionary 這樣的泛型集合提供了對任何特定類型的類型安全且高效的存儲,消除了強制轉換的需要,並減少了運行時錯誤。

我如何在 C# 中創建自定義泛型類型?

您可以創建自定義泛型類型來封裝不同數據類型中常見但以類型特定方式處理的操作,這在構建庫或工具時非常有用。

C# 泛型如何改善 .NET 中的 PDF 生成?

C# 泛型可以與 PDF 庫一起使用,以創建靈活且可重用的組件。例如,可以使用一個 PdfOptions 類來保存 PDF 生成選項,這展示了泛型在 PDF 任務中的適應性。

如何使用 C# 泛型利用 PDF 庫?

如 IronPDF 的 PDF 庫可以使用 C# 泛型來增強其功能。例如,泛型方法可以用於將 HTML 轉換為 PDF,提供了一種靈活的文檔生成方法。

使用 C# 泛型有哪些優勢?

C# 泛型允許在不同數據類型間重用代碼,確保編譯時類型檢查,減少運行時錯誤,提高整體代碼質量。它們使編寫靈活和易於維護的代碼成為可能。

Curtis Chau
技術作家

Curtis Chau 擁有卡爾頓大學計算機科學學士學位,專注於前端開發,擅長於 Node.js、TypeScript、JavaScript 和 React。Curtis 熱衷於創建直觀且美觀的用戶界面,喜歡使用現代框架並打造結構良好、視覺吸引人的手冊。

除了開發之外,Curtis 對物聯網 (IoT) 有著濃厚的興趣,探索將硬體和軟體結合的創新方式。在閒暇時間,他喜愛遊戲並構建 Discord 機器人,結合科技與創意的樂趣。