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(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 ClassPublic 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")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 ClassPublic 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)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 InterfacePublic 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)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")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 ClassPublic 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 ClassIronPDF: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 ClassPublic Class PdfOptions(Of T)
Public Property Metadata As T
Public Property HtmlContent As String
End Class現在,讓我們建立一個使用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)(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 ModuleImports 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 ClassFriend 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# Generics(其如何對開發者運作):圖1 - 使用泛型從HTML字串生成PDF文件的範例程式碼輸出使用IronPDF
結論
C# Generics(其如何對開發者運作):圖2 - IronPDF授權頁面
C# 泛型是開發高品質、可重複使用和型別安全程式碼的強大工具。 透過了解和應用泛型類別、方法、介面和委派,您可以編寫出更能適應的程式碼,且更易於維護。 泛型不僅可以跨不同資料型別重用程式碼,還可確保編譯時型別檢查,這減少了執行時錯誤並提高了整體程式碼質量。 IronPDF提供其PDF程式庫工具的免費試用,費用從$999起。
Jacob Mellor是Iron Software的首席技術官,一位在C# PDF技術上開創先河的遠見工程師。作為Iron Software核心程式碼庫的原開發者,他從創立以來就一直在塑造公司的產品架構,與首席執行官Cameron Rimington一起將公司轉變為服務於NASA、特斯拉和全球政府公司的50多名人員的公司。