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)
Private data As T
Public Sub New(data As T)
Me.data = data
End Sub
Public ReadOnly Property Data As T
Get
Return data
End Get
End Property
End Class
要使用此類,您需要建立一個實例,並指定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")
這段程式碼示範如何使用單一類別( Box) ) 可以適應儲存不同的資料類型( int 、 string ),展現了泛型在程式碼重複使用和類型安全性方面的強大功能。
實作泛型方法
泛型方法類似於泛型類別,但在方法層級中使用類型參數定義。 這允許建立可操作不同類型的方法,同時在非泛型類別或泛型類別中定義。
泛型方法範例
這裡有一個方法,可以交換任何類型陣列中的兩個元素:
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
上述方法的用法可以如下:
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)
探索泛型介面和委派
泛型介面和委派能夠定義可以操作任何類型的契約和回呼方法。 在您的類別或方法中實作泛型介面或使用泛型委派,可以增強靈活性和程式碼的重複使用。
泛型介面範例
資料存取作業的泛型儲存庫介面可能是這樣的:
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(item As T)
Function GetById(id As Integer) As T
Function GetAll() As IEnumerable(Of T)
End Interface
此介面可由任何類別實作,以處理特定的資料類型,讓不同類型的資料存取模式保持一致。
泛型委派範例
泛型委派可用於定義類型安全的回呼:
public delegate void Action<t>(T item);
public delegate void Action<t>(T item);
Public Delegate Sub Action(Of T)(item As T)
使用泛型集合
泛型集合類別,例如 List、Dictionary<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")
建立自訂泛型類型
除了使用內建的泛型類型之外,您也可以建立自己的泛型類型,以封裝不同資料類型共通但需要以特定類型方式處理的作業。 這種方法特別適用於建立要使用各種資料類型的函式庫、架構或公用程式。
自訂泛型類型範例
考慮一個泛型的 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)
Public ReadOnly Property Success As Boolean
Public ReadOnly Property Data As T
Public ReadOnly Property Message As String
Public Sub New(success As Boolean, data As T, Optional message As String = "")
Me.Success = success
Me.Data = data
Me.Message = message
End Sub
End Class
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
現在,讓我們建立一個靜態方法,利用 IronPDF 和我們的 PdfOptions 類別來產生 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)(options As PdfOptions(Of T))
' Initialize the IronPDF HtmlToPdf renderer
Dim renderer As 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
If TypeOf options.Metadata Is String Then
Dim metadataString As String = CType(options.Metadata, String)
Console.WriteLine($"Metadata: {metadataString}")
End If
' Save the PDF to a file
Dim fileName As String = $"GeneratedPdf_{DateTime.Now.Ticks}.pdf"
pdfDocument.SaveAs(fileName)
Console.WriteLine($"PDF generated and saved as {fileName}")
End Sub
End Module
最後,讓我們使用 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
此範例示範了將 IronPDF 與 C# 泛型整合的基本原理,提供了一種靈活的方式來從 HTML 內容產生 PDF,同時允許透過泛型的 PdfOptions 類別自訂元資料或配置。 您可以根據應用程式的需要,在此基礎上增加更複雜的選項和渲染器組態。

結論

C# 泛型是開發高品質、可重複使用且類型安全程式碼的強大工具。 透過了解並應用泛型類別、方法、介面和委託,您可以寫出更具適應性、更容易維護的程式碼。 泛型不僅能讓程式碼在不同的資料類型間重複使用,還能確保編譯時的類型檢查,從而減少執行時的錯誤並提昇整體程式碼品質。 IronPDF 提供其 PDF 函式庫工具的免費試用版,費用從 $999 起。
常見問題解答
什麼是 C# 中的泛型?
C# 泛型引入了一種通過類型參數設計類別、方法、介面和委託的方法。這允許創建提供類型安全性和性能改進的靈活且可重用的程式碼組件。
泛型類別在 C# 中如何運作?
C# 中的泛型類別使用類型參數,通常標記為 T,作為它所包含或運行的類型的佔位符。這允許類別在保持類型安全性的同時用各種數據類型實例化。
您能給出一個 C# 泛型類的例子嗎?
是的,一個簡單的例子是 Box 類,用於存儲任何類型的值。您可以像 Box 或 Box 這樣創建實例,以便使用相同的類存儲不同的數據類型。
什麼是 C# 中的泛型方法?
泛型方法在方法層中定義類型參數,允許它操作不同的類型。它可以是非泛型類或泛型類的一部分,使方法設計更具靈活性。
在 C# 中如何使用泛型介面和委託?
泛型介面和委託允許定義可以用任何類型運行的合約和回調方法,增強了靈活性和程式碼重用性。
在 C# 中使用泛型集合有哪些好處?
像 List 和 Dictionary 這樣的泛型集合提供了對任何特定類型的類型安全且高效的存儲,消除了強制轉換的需要,並減少了運行時錯誤。
我如何在 C# 中創建自定義泛型類型?
您可以創建自定義泛型類型來封裝不同數據類型中常見但以類型特定方式處理的操作,這在構建庫或工具時非常有用。
C# 泛型如何改善 .NET 中的 PDF 生成?
C# 泛型可以與 PDF 庫一起使用,以創建靈活且可重用的組件。例如,可以使用一個 PdfOptions 類來保存 PDF 生成選項,這展示了泛型在 PDF 任務中的適應性。
如何使用 C# 泛型利用 PDF 庫?
如 IronPDF 的 PDF 庫可以使用 C# 泛型來增強其功能。例如,泛型方法可以用於將 HTML 轉換為 PDF,提供了一種靈活的文檔生成方法。
使用 C# 泛型有哪些優勢?
C# 泛型允許在不同數據類型間重用程式碼,確保編譯時類型檢查,減少運行時錯誤,提高整體程式碼品質。它們使編寫靈活和易於維護的程式碼成為可能。



