跳至页脚内容
.NET 帮助

C# 虚拟与抽象(开发人员如何使用)

在 C# 中, 虚方法 可以在派生类中被重写,而抽象方法必须在派生类中重写。 这允许灵活的行为并在面向对象编程中启用多态性。 这两个概念在面向对象编程中允许灵活性和可重用性。 本文解释了抽象方法和虚方法的具体细节,提供了清晰的示例,并专注于它们在编码中的实际用途。 我们还将探讨文章后面的IronPDF 功能和用例

抽象类和方法

抽象类是一种特殊类型的类,不能直接实例化。 相反,它作为其他类的蓝图。 抽象类可以包含抽象方法,这些方法在抽象类中声明,但必须在具体派生类中实现。

public abstract class Vehicle
{
    // Abstract method to be implemented in non-abstract child class
    public abstract void DisplayInfo();
}
public abstract class Vehicle
{
    // Abstract method to be implemented in non-abstract child class
    public abstract void DisplayInfo();
}
Public MustInherit Class Vehicle
	' Abstract method to be implemented in non-abstract child class
	Public MustOverride Sub DisplayInfo()
End Class
$vbLabelText   $csharpLabel

在这个例子中,Vehicle 类是抽象的,DisplayInfo 是一个抽象方法。 DisplayInfo 方法在 Vehicle 类中没有任何实现。 它迫使派生类提供其自己的方法定义。

虚方法

虚方法是基类中的方法,它有一个默认实现,但可以在派生类中重写。 关键字用于声明一个方法为虚方法。 派生类使用 override 关键字为方法提供特定实现,这有助于理解子类如何重写其父类的虚方法。

// Non-abstract class
public class Animal
{
    // Virtual method with a default implementation
    public virtual void Speak()
    {
        Console.WriteLine("Some generic animal sound");
    }
}
// Non-abstract class
public class Animal
{
    // Virtual method with a default implementation
    public virtual void Speak()
    {
        Console.WriteLine("Some generic animal sound");
    }
}
' Non-abstract class
Public Class Animal
	' Virtual method with a default implementation
	Public Overridable Sub Speak()
		Console.WriteLine("Some generic animal sound")
	End Sub
End Class
$vbLabelText   $csharpLabel

这里,Animal 类有一个名为 Speak 的虚方法,带有默认实现。 派生类可以重写这个方法,以使用 override 关键字提供特定的动物声音。

结合虚方法和抽象方法

一个类可以同时拥有抽象方法和虚方法。 抽象方法没有实现,必须在派生类中重写,而虚方法有一个默认实现,派生类可以选择重写。

考虑一个场景,您正在构建一个系统,该系统模拟不同类型的车辆,每种车辆都有其显示信息的方法。 以下是您如何使用抽象和虚方法:

public abstract class Vehicle
{
    // Abstract method
    public abstract void DisplayInfo();

    // Virtual method
    public virtual void StartEngine()
    {
        Console.WriteLine("Engine started with default configuration.");
    }
}
public abstract class Vehicle
{
    // Abstract method
    public abstract void DisplayInfo();

    // Virtual method
    public virtual void StartEngine()
    {
        Console.WriteLine("Engine started with default configuration.");
    }
}
Public MustInherit Class Vehicle
	' Abstract method
	Public MustOverride Sub DisplayInfo()

	' Virtual method
	Public Overridable Sub StartEngine()
		Console.WriteLine("Engine started with default configuration.")
	End Sub
End Class
$vbLabelText   $csharpLabel

在这个 Vehicle 类中,DisplayInfo 是一个抽象方法,迫使所有派生类实现其显示信息的方式。 但是,StartEngine 提供了一个默认的启动引擎方法,如果需要,子类可以重写它。

派生类的例子

现在,我们定义一个 Car 类,一个继承自 Vehicle 的非抽象子类,并实现抽象方法,同时可选地重写虚方法:

public class Car : Vehicle
{
    // Override the abstract method
    public override void DisplayInfo()
    {
        Console.WriteLine("This is a car.");
    }

    // Override the virtual method
    public override void StartEngine()
    {
        Console.WriteLine("Car engine started with custom settings.");
    }
}
public class Car : Vehicle
{
    // Override the abstract method
    public override void DisplayInfo()
    {
        Console.WriteLine("This is a car.");
    }

    // Override the virtual method
    public override void StartEngine()
    {
        Console.WriteLine("Car engine started with custom settings.");
    }
}
Public Class Car
	Inherits Vehicle

	' Override the abstract method
	Public Overrides Sub DisplayInfo()
		Console.WriteLine("This is a car.")
	End Sub

	' Override the virtual method
	Public Overrides Sub StartEngine()
		Console.WriteLine("Car engine started with custom settings.")
	End Sub
End Class
$vbLabelText   $csharpLabel

这里,Car 类为抽象方法 DisplayInfo 和虚方法 StartEngine 提供了具体实现。

区别以及何时使用

  • 当所有派生类都必须提供其方法的实现时,使用抽象方法。
  • 当派生类应该有选择权以重写默认或提供额外行为时,使用虚方法。

抽象方法和虚方法是 C# 中强大的特性,使您能够编写更可维护和可重用的代码。 通过在基类中将方法定义为抽象或虚方法,您可以指示哪些方法必须在派生类中重写,哪些方法可以选择性地重写以修改或扩展默认行为。

重写虚方法

在派生类中重写虚拟方法允许自定义行为,同时保留调用基类实现的选项。 这是通过使用 base 关键字实现的。

重写和调用基类实现的例子

public class ElectricCar : Car
{
    // Override the StartEngine method
    public override void StartEngine()
    {
        base.StartEngine(); // Call the base class implementation
        Console.WriteLine("Electric car engine started with energy-saving mode.");
    }
}
public class ElectricCar : Car
{
    // Override the StartEngine method
    public override void StartEngine()
    {
        base.StartEngine(); // Call the base class implementation
        Console.WriteLine("Electric car engine started with energy-saving mode.");
    }
}
Public Class ElectricCar
	Inherits Car

	' Override the StartEngine method
	Public Overrides Sub StartEngine()
		MyBase.StartEngine() ' Call the base class implementation
		Console.WriteLine("Electric car engine started with energy-saving mode.")
	End Sub
End Class
$vbLabelText   $csharpLabel

在这个例子中,ElectricCar,它是 Car 的子类,重写了从其父类继承的 StartEngine 方法。 它调用基类实现并添加特定于电动汽车的其他行为。

实现抽象类和非抽象类

了解抽象类和非抽象类在软件开发中的实用差异和应用至关重要。 抽象类作为其他类的模板,而非抽象类用于实例化对象。 选择使用抽象类还是非抽象类取决于您是否需要创建一个不应该自行实例化的基类。

探索 IronPDF 用于 PDF 管理 是一个为使用 C# 编程语言的开发人员提供的工具,允许他们在其应用程序内部直接创建、读取和编辑 PDF 文档。

C# Virtual Vs Abstract (开发者如何工作):图 1 - IronPDF

IronPDF 是一个全面的 PDF 库,专为在 .NET 应用程序中直接生成、编辑和读取 PDF 文档而设计。 这个工具因能够从HTML 字符串、文件和 URL 直接创建 PDF 而脱颖而出。 开发者可以在 C# 项目中程序化地创建、修改和提取 PDF 内容。 让我们在本文中探讨 IronPDF 的一个例子。

IronPDF 的主要功能是将HTML 转换为 PDF,确保布局和样式得以保留。 这个工具非常适合从网页内容创建报告、发票和文档的 PDF。 它支持将 HTML 文件、URL 和 HTML 字符串转换为 PDF 文件。

using IronPdf;

class Program
{
    static void Main(string[] args)
    {
        var renderer = new ChromePdfRenderer();

        // Convert HTML String to PDF
        var htmlContent = "<h1>Hello, IronPDF!</h1><p>This is a PDF from an HTML string.</p>";
        var pdfFromHtmlString = renderer.RenderHtmlAsPdf(htmlContent);
        pdfFromHtmlString.SaveAs("HTMLStringToPDF.pdf");

        // Convert HTML File to PDF
        var htmlFilePath = "path_to_your_html_file.html"; // Specify the path to your HTML file
        var pdfFromHtmlFile = renderer.RenderHtmlFileAsPdf(htmlFilePath);
        pdfFromHtmlFile.SaveAs("HTMLFileToPDF.pdf");

        // Convert URL to PDF
        var url = "http://ironpdf.com"; // Specify the URL
        var pdfFromUrl = renderer.RenderUrlAsPdf(url);
        pdfFromUrl.SaveAs("URLToPDF.pdf");
    }
}
using IronPdf;

class Program
{
    static void Main(string[] args)
    {
        var renderer = new ChromePdfRenderer();

        // Convert HTML String to PDF
        var htmlContent = "<h1>Hello, IronPDF!</h1><p>This is a PDF from an HTML string.</p>";
        var pdfFromHtmlString = renderer.RenderHtmlAsPdf(htmlContent);
        pdfFromHtmlString.SaveAs("HTMLStringToPDF.pdf");

        // Convert HTML File to PDF
        var htmlFilePath = "path_to_your_html_file.html"; // Specify the path to your HTML file
        var pdfFromHtmlFile = renderer.RenderHtmlFileAsPdf(htmlFilePath);
        pdfFromHtmlFile.SaveAs("HTMLFileToPDF.pdf");

        // Convert URL to PDF
        var url = "http://ironpdf.com"; // Specify the URL
        var pdfFromUrl = renderer.RenderUrlAsPdf(url);
        pdfFromUrl.SaveAs("URLToPDF.pdf");
    }
}
Imports IronPdf

Friend Class Program
	Shared Sub Main(ByVal args() As String)
		Dim renderer = New ChromePdfRenderer()

		' Convert HTML String to PDF
		Dim htmlContent = "<h1>Hello, IronPDF!</h1><p>This is a PDF from an HTML string.</p>"
		Dim pdfFromHtmlString = renderer.RenderHtmlAsPdf(htmlContent)
		pdfFromHtmlString.SaveAs("HTMLStringToPDF.pdf")

		' Convert HTML File to PDF
		Dim htmlFilePath = "path_to_your_html_file.html" ' Specify the path to your HTML file
		Dim pdfFromHtmlFile = renderer.RenderHtmlFileAsPdf(htmlFilePath)
		pdfFromHtmlFile.SaveAs("HTMLFileToPDF.pdf")

		' Convert URL to PDF
		Dim url = "http://ironpdf.com" ' Specify the URL
		Dim pdfFromUrl = renderer.RenderUrlAsPdf(url)
		pdfFromUrl.SaveAs("URLToPDF.pdf")
	End Sub
End Class
$vbLabelText   $csharpLabel

代码示例

这是一个简单的实际代码示例,以说明在扩展 IronPDF 功能时使用 抽象 关键字的用法:

public abstract class PdfReportGenerator
{
    // Use abstract method to force derived classes to implement their custom PDF generation logic
    public abstract void GenerateReport(string filePath);

    // A virtual function allows derived classes to override the default implementation of PDF setup
    public virtual void SetupPdfGenerator()
    {
        // Default PDF setup logic that can be overridden by derived classes
        IronPdf.Installation.TempFolderPath = @"F:\TempPdfFiles";
    }
}

public class MonthlyReportGenerator : PdfReportGenerator
{
    // Override abstract method to provide specific implementation
    public override void GenerateReport(string filePath)
    {
        var pdf = new ChromePdfRenderer();
        pdf.RenderHtmlAsPdf("<h1>Monthly Report</h1> <p>Add Your report content here....</p>").SaveAs(filePath);
    }

    // Optionally override the virtual method to customize the setup
    public override void SetupPdfGenerator()
    {
        base.SetupPdfGenerator();
        // Additional setup logic specific to monthly reports
        IronPdf.Installation.TempFolderPath = @"F:\MonthlyReports";
    }
}

class Program
{
    static void Main(string[] args)
    {
        License.LicenseKey = "License-Key";
        PdfReportGenerator reportGenerator = new MonthlyReportGenerator();
        reportGenerator.SetupPdfGenerator();
        reportGenerator.GenerateReport(@"F:\MonthlyReports\MonthlyReport.pdf");
        Console.WriteLine("Report generated successfully.");
    }
}
public abstract class PdfReportGenerator
{
    // Use abstract method to force derived classes to implement their custom PDF generation logic
    public abstract void GenerateReport(string filePath);

    // A virtual function allows derived classes to override the default implementation of PDF setup
    public virtual void SetupPdfGenerator()
    {
        // Default PDF setup logic that can be overridden by derived classes
        IronPdf.Installation.TempFolderPath = @"F:\TempPdfFiles";
    }
}

public class MonthlyReportGenerator : PdfReportGenerator
{
    // Override abstract method to provide specific implementation
    public override void GenerateReport(string filePath)
    {
        var pdf = new ChromePdfRenderer();
        pdf.RenderHtmlAsPdf("<h1>Monthly Report</h1> <p>Add Your report content here....</p>").SaveAs(filePath);
    }

    // Optionally override the virtual method to customize the setup
    public override void SetupPdfGenerator()
    {
        base.SetupPdfGenerator();
        // Additional setup logic specific to monthly reports
        IronPdf.Installation.TempFolderPath = @"F:\MonthlyReports";
    }
}

class Program
{
    static void Main(string[] args)
    {
        License.LicenseKey = "License-Key";
        PdfReportGenerator reportGenerator = new MonthlyReportGenerator();
        reportGenerator.SetupPdfGenerator();
        reportGenerator.GenerateReport(@"F:\MonthlyReports\MonthlyReport.pdf");
        Console.WriteLine("Report generated successfully.");
    }
}
Public MustInherit Class PdfReportGenerator
	' Use abstract method to force derived classes to implement their custom PDF generation logic
	Public MustOverride Sub GenerateReport(ByVal filePath As String)

	' A virtual function allows derived classes to override the default implementation of PDF setup
	Public Overridable Sub SetupPdfGenerator()
		' Default PDF setup logic that can be overridden by derived classes
		IronPdf.Installation.TempFolderPath = "F:\TempPdfFiles"
	End Sub
End Class

Public Class MonthlyReportGenerator
	Inherits PdfReportGenerator

	' Override abstract method to provide specific implementation
	Public Overrides Sub GenerateReport(ByVal filePath As String)
		Dim pdf = New ChromePdfRenderer()
		pdf.RenderHtmlAsPdf("<h1>Monthly Report</h1> <p>Add Your report content here....</p>").SaveAs(filePath)
	End Sub

	' Optionally override the virtual method to customize the setup
	Public Overrides Sub SetupPdfGenerator()
		MyBase.SetupPdfGenerator()
		' Additional setup logic specific to monthly reports
		IronPdf.Installation.TempFolderPath = "F:\MonthlyReports"
	End Sub
End Class

Friend Class Program
	Shared Sub Main(ByVal args() As String)
		License.LicenseKey = "License-Key"
		Dim reportGenerator As PdfReportGenerator = New MonthlyReportGenerator()
		reportGenerator.SetupPdfGenerator()
		reportGenerator.GenerateReport("F:\MonthlyReports\MonthlyReport.pdf")
		Console.WriteLine("Report generated successfully.")
	End Sub
End Class
$vbLabelText   $csharpLabel

在这个自定义实现示例中,PdfReportGenerator 是一个抽象类,它定义了生成 PDF 报告的契约,具有一个用于生成报告的方法和一个可以选择性地被重写的虚方法。 MonthlyReportGenerator 是一个具体实现,它提供了生成月度报告的详细信息,并通过重写虚方法来定制设置。

C# Virtual Vs Abstract (开发者如何工作):图 2 - 报告输出

结论

C# Virtual Vs Abstract (开发者如何工作):图 3 - 授权

有效地理解和使用虚方法和抽象方法可以显著增强您的 C# 编程。 记住,抽象方法要求派生类提供实现,而虚方法允许选择性地覆盖默认实现。 IronPDF 库提供 免费试用版和授权选项,授权起价为 $799,为您的 PDF 需求提供全面的解决方案。

常见问题解答

什么是 C# 中的虚拟方法?

C# 中的虚拟方法是包含默认实现的方法,派生类可以覆盖它们以提供具体行为,从而促进代码设计的灵活性。

如何使用 IronPDF 在 C# 中将 HTML 转换为 PDF?

您可以使用 IronPDF 的 RenderHtmlAsPdf 方法将 HTML 字符串转换为 PDF。这使您可以在生成的 PDF 文档中保持 HTML 内容的布局和样式。

C# 中的虚拟方法和抽象方法有什么区别?

虚拟方法有默认实现,可以选择在派生类中覆盖,而抽象方法没有实现,必须在派生类中覆盖。

IronPDF 如何帮助在 .NET 应用程序中生成 PDF?

IronPDF 是一个强大的库,可以在 .NET 应用程序中生成、编辑和读取 PDF 文档。它允许从 HTML 内容创建 PDF,确保布局得以保留。

什么是 C# 中的抽象方法?

抽象方法是在抽象类中声明而没有实现的方法,必须在任何非抽象派生类中实现,以确保派生类中的具体行为。

C# 中的类可以同时具有虚拟方法和抽象方法吗?

是的,一个类可以包含虚拟方法和抽象方法。虚拟方法提供默认实现,而抽象方法需要在派生类中进行显式实现。

如何在派生类中覆盖虚拟方法?

要在派生类中覆盖虚拟方法,可以使用 override 关键字,后跟方法的签名,以实现新的或扩展的实现。

开发人员应该在何时使用 C# 的虚拟方法?

开发人员在需要默认行为时应使用虚拟方法,该行为可以由派生类选择性地覆盖,从而促进多态性和代码可重用性。

在C#项目中使用IronPDF有哪些好处?

IronPDF 通过提供强大的 PDF 生成和操作功能,如将 HTML 转换为 PDF,并保持文档的设计完整性,增强了 C# 项目。

IronPDF 如何确保 PDF 文档的布局得以保留?

IronPDF 通过准确地将 HTML 字符串、文件或 URL 转换为 PDF 格式,确保输出中保留所有样式和布局。

Curtis Chau
技术作家

Curtis Chau 拥有卡尔顿大学的计算机科学学士学位,专注于前端开发,精通 Node.js、TypeScript、JavaScript 和 React。他热衷于打造直观且美观的用户界面,喜欢使用现代框架并创建结构良好、视觉吸引力强的手册。

除了开发之外,Curtis 对物联网 (IoT) 有浓厚的兴趣,探索将硬件和软件集成的新方法。在空闲时间,他喜欢玩游戏和构建 Discord 机器人,将他对技术的热爱与创造力相结合。