跳過到頁腳內容
.NET幫助

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

C# 泛型引入了一種設計類別、方法、介面和委派的方法,在這些類別、方法、介面和委派中,它們所管理的資料類型可以指定為參數。 此概念稱為泛型參數,可建立彈性且可重用的程式碼元件。 透過使用 泛型,您可以將程式碼的重複使用性、類型安全性和效能發揮到極致。 舉例來說,一個泛型類別可以定義一次,但實體化為各種資料類型,提供多樣性和類型完整性。 在這篇文章中,我們將學習 C# Generics 的基礎知識以及 用於 PDF 操作的 IronPDF 函式庫功能

泛型類的基礎知識

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 的虛擬關鍵字。

在此使用泛型背後的想法是要建立一個可重複使用的方法,可以從任何給定的 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

現在,讓我們利用 PdfOptions 類,建立一個使用 IronPDF 產生 PDF 的靜態方法。 此方法將使用 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# Generics 整合的基本原理,提供一種靈活的方式從 HTML 內容產生 PDF,同時允許透過泛型 PdfOptions 類別自訂元資料或配置。 您可以根據應用程式的需要,在此基礎上增加更複雜的選項和呈現器組態。

C# Generics (How It Works For Developers):圖 1 - 利用 IronPDF 從 HTML 字串建立 PDF 文件的泛型程式碼輸出範例

結論

C# Generics (How It Works For Developers):圖 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 函式庫?

PDF 函式庫,例如 IronPDF,可以使用 C# 泛型來增強其功能。例如,可以使用泛型方法將 HTML 轉換為 PDF,提供彈性的文件產生方法。

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

C# 泛型允許跨不同資料類型重複使用程式碼、確保編譯時型別檢查、減少執行時錯誤,並改善整體程式碼品質。它們使編寫的程式碼具有適應性和可維護性。

Jacob Mellor, Team Iron 首席技术官
首席技术官

Jacob Mellor 是 Iron Software 的首席技術官,作為 C# PDF 技術的先鋒工程師。作為 Iron Software 核心代碼的原作者,他自開始以來塑造了公司產品架構,與 CEO Cameron Rimington 一起將其轉變為一家擁有超過 50 名員工的公司,為 NASA、特斯拉 和 全世界政府機構服務。

Jacob 持有曼徹斯特大學土木工程一級榮譽学士工程學位(BEng) (1998-2001)。他於 1999 年在倫敦開設了他的第一家軟件公司,並於 2005 年製作了他的首個 .NET 組件,專注於解決 Microsoft 生態系統內的複雜問題。

他的旗艦產品 IronPDF & Iron Suite .NET 庫在全球 NuGet 被安裝超過 3000 萬次,其基礎代碼繼續為世界各地的開發工具提供動力。擁有 25 年的商業經驗和 41 年的編碼專業知識,Jacob 仍專注於推動企業級 C#、Java 及 Python PDF 技術的創新,同時指導新一代技術領袖。