C# Virtual Keyword (How It Works For Developers)

In C#, the virtual keyword is a pivotal concept in object-oriented programming that facilitates polymorphism, allowing developers to override methods in derived classes. This keyword, when applied to a class method, property, or event, indicates that the entity can have its behavior modified by a derived class using the override keyword. In this tutorial, we'll learn about C# Virtual Keyword and IronPDF library. Let's dive straight into how it works and see it in action with practical examples.

Virtual Methods in Action

Basic Usage of Virtual Keyword

At its core, a virtual method is a base class method that allows derived classes to provide a specific implementation for methods that are already defined in the base class.

The virtual keyword in C# marks a method, property, or event as virtual, signaling that it can be overridden in any class inheriting from it. Consider the following example where we define a base class Shape with a virtual method Area:

public class Shape
{
    public virtual double Area()
    {
        return 0; // Default implementation, returns 0
    }
}
public class Shape
{
    public virtual double Area()
    {
        return 0; // Default implementation, returns 0
    }
}
Public Class Shape
	Public Overridable Function Area() As Double
		Return 0 ' Default implementation, returns 0
	End Function
End Class
VB   C#

Overriding Virtual Methods

Derived classes can override these virtual methods to provide their own implementation, tailored to the specific requirements of the derived class. Using the override keyword, let's create a Circle class that derives from Shape and provides its own version of the Area method:

public class Circle : Shape
{
    public double Radius { get; set; }
    public Circle(double radius)
    {
        Radius = radius;
    }
    public override double Area()
    {
        return Math.PI * Radius * Radius; // Own implementation for circle area
    }
}
public class Circle : Shape
{
    public double Radius { get; set; }
    public Circle(double radius)
    {
        Radius = radius;
    }
    public override double Area()
    {
        return Math.PI * Radius * Radius; // Own implementation for circle area
    }
}
Public Class Circle
	Inherits Shape

	Public Property Radius() As Double
	Public Sub New(ByVal radius As Double)
		Me.Radius = radius
	End Sub
	Public Overrides Function Area() As Double
		Return Math.PI * Radius * Radius ' Own implementation for circle area
	End Function
End Class
VB   C#

In the above code, the Circle class provides its specific implementation of the Area method, which calculates the area of a circle. This demonstrates the power of virtual methods in polymorphism.

Non-Virtual Methods

It's important to note that not all methods need to be or should be virtual. A non-virtual method is defined in such a way that it cannot be overridden in derived classes, which means the initial implementation remains unchanged and is utilized by all classes that inherit from it. This is useful when a base class provides a standard implementation that should not be altered.

Practical Application

Let's put these concepts to work in a practical scenario. Consider the following program that uses our Shape and Circle classes:

public class Program
{
    public static void Main(string[] args)
    {
        Shape myShape = new Shape();
        Shape myCircle = new Circle(5);
        Console.WriteLine($"Shape area: {myShape.Area()}");
        Console.WriteLine($"Circle area: {myCircle.Area()}");
    }
}
public class Program
{
    public static void Main(string[] args)
    {
        Shape myShape = new Shape();
        Shape myCircle = new Circle(5);
        Console.WriteLine($"Shape area: {myShape.Area()}");
        Console.WriteLine($"Circle area: {myCircle.Area()}");
    }
}
Public Class Program
	Public Shared Sub Main(ByVal args() As String)
		Dim myShape As New Shape()
		Dim myCircle As Shape = New Circle(5)
		Console.WriteLine($"Shape area: {myShape.Area()}")
		Console.WriteLine($"Circle area: {myCircle.Area()}")
	End Sub
End Class
VB   C#

The above example program demonstrates polymorphism in action and the essence of virtual function. Despite myCircle being declared as a Shape, it calls the overridden Area method from the Circle class, showcasing the dynamic dispatch mechanism facilitated by the virtual and override keywords.

C# Virtual Keyword (How It Works For Developers): Figure 1 - Console output from the code above showcasing how myCircle calls the overridden Area method

Advanced Uses of Virtual and Override Keywords

Abstract Methods and Classes

Abstract methods are a step further, used in abstract classes. An abstract method is a method declared in the base class without an implementation and must be overridden in derived classes. It forces derived classes to provide an implementation for the abstract method, ensuring a consistent interface while allowing for customized behavior in each derived class.

Method Overloading vs. Overriding

It's also crucial to understand the difference between method overloading and method overriding. Method overloading occurs within the same class and allows more than one method to have the same name but different parameters. Method overriding, facilitated by virtual and override keywords, allows a derived class to provide a different implementation for a method defined in the base class.

Virtual Properties and Events

Besides methods, properties, and events can also be virtual. This enables derived classes to provide custom getters, setters, and event handlers, further enhancing the flexibility of class hierarchies.

IronPDF: .NET PDF Library

IronPDF is a comprehensive library designed for C# developers to generate, manipulate, and render PDF documents directly within .NET applications. It offers an intuitive API that simplifies working with PDF files, helping developers to create, edit, and convert PDFs without needing to understand the complex underlying PDF document structure or resort to external software. IronPDF seamlessly integrates with the language's object-oriented features, including the use of the virtual keyword, to provide customizable PDF processing capabilities.

Using the virtual keyword with IronPDF allows developers to extend the functionality of IronPDF's classes within their applications. By defining base classes with virtual methods related to PDF generation or manipulation, developers can create derived classes that override these methods to tailor the PDF processing behavior to specific needs.

Example: Customizing PDF Rendering with Virtual Methods

Imagine you have a base class that uses IronPDF to render PDFs from HTML strings. By marking the rendering method as virtual, you allow derived classes to modify or enhance the rendering process. Here's a simple example:

public class BasicPdfRenderer
{
    // Virtual method allowing customization in derived classes
    public virtual byte[] RenderHtmlToPdf(string htmlContent)
    {
        // Use IronPDF to render PDF from HTML
        var renderer = new IronPdf.ChromePdfRenderer();
        var pdfDocument = renderer.RenderHtmlAsPdf(htmlContent);
        return pdfDocument.BinaryData;
    }
}
public class CustomPdfRenderer : BasicPdfRenderer
{
    // Overriding the base class method to implement custom rendering settings
    public override byte[] RenderHtmlToPdf(string htmlContent)
    {
        var renderer = new IronPdf.ChromePdfRenderer();
        var pdfDocument = renderer.RenderHtmlAsPdf(htmlContent);
        // Apply a prominent watermark to the PDF document
        pdfDocument.ApplyWatermark("<h2 style='color:red; font-size: 60px; opacity: 0.5; text-shadow: 2px 2px 5px grey;'>SAMPLE</h2>",
                                      30,
                                      IronPdf.Editing.VerticalAlignment.Middle,
                                      IronPdf.Editing.HorizontalAlignment.Center);
        // Return the binary data of the PDF document
        return pdfDocument.BinaryData;
    }
}
class Program
{
    static void Main(string[] args)
    {
        License.LicenseKey = "License-Key";
        // HTML content to be converted to PDF
        string htmlContent = "<h1>Hello, IronPDF!</h1><p>This is a simple PDF document generated from HTML.</p>";
        // Create an instance of CustomPdfRenderer
        CustomPdfRenderer renderer = new CustomPdfRenderer();
        // Call RenderHtmlToPdf method to generate PDF binary data
        byte[] pdfData = renderer.RenderHtmlToPdf(htmlContent);
        // Specify the file path to save the PDF
        string filePath = "f:\\CustomRenderedPdf.pdf";
        // Save the binary data to a file
        File.WriteAllBytes(filePath, pdfData);
        Console.WriteLine($"PDF generated and saved to {filePath}");
    }
}
public class BasicPdfRenderer
{
    // Virtual method allowing customization in derived classes
    public virtual byte[] RenderHtmlToPdf(string htmlContent)
    {
        // Use IronPDF to render PDF from HTML
        var renderer = new IronPdf.ChromePdfRenderer();
        var pdfDocument = renderer.RenderHtmlAsPdf(htmlContent);
        return pdfDocument.BinaryData;
    }
}
public class CustomPdfRenderer : BasicPdfRenderer
{
    // Overriding the base class method to implement custom rendering settings
    public override byte[] RenderHtmlToPdf(string htmlContent)
    {
        var renderer = new IronPdf.ChromePdfRenderer();
        var pdfDocument = renderer.RenderHtmlAsPdf(htmlContent);
        // Apply a prominent watermark to the PDF document
        pdfDocument.ApplyWatermark("<h2 style='color:red; font-size: 60px; opacity: 0.5; text-shadow: 2px 2px 5px grey;'>SAMPLE</h2>",
                                      30,
                                      IronPdf.Editing.VerticalAlignment.Middle,
                                      IronPdf.Editing.HorizontalAlignment.Center);
        // Return the binary data of the PDF document
        return pdfDocument.BinaryData;
    }
}
class Program
{
    static void Main(string[] args)
    {
        License.LicenseKey = "License-Key";
        // HTML content to be converted to PDF
        string htmlContent = "<h1>Hello, IronPDF!</h1><p>This is a simple PDF document generated from HTML.</p>";
        // Create an instance of CustomPdfRenderer
        CustomPdfRenderer renderer = new CustomPdfRenderer();
        // Call RenderHtmlToPdf method to generate PDF binary data
        byte[] pdfData = renderer.RenderHtmlToPdf(htmlContent);
        // Specify the file path to save the PDF
        string filePath = "f:\\CustomRenderedPdf.pdf";
        // Save the binary data to a file
        File.WriteAllBytes(filePath, pdfData);
        Console.WriteLine($"PDF generated and saved to {filePath}");
    }
}
Public Class BasicPdfRenderer
	' Virtual method allowing customization in derived classes
	Public Overridable Function RenderHtmlToPdf(ByVal htmlContent As String) As Byte()
		' Use IronPDF to render PDF from HTML
		Dim renderer = New IronPdf.ChromePdfRenderer()
		Dim pdfDocument = renderer.RenderHtmlAsPdf(htmlContent)
		Return pdfDocument.BinaryData
	End Function
End Class
Public Class CustomPdfRenderer
	Inherits BasicPdfRenderer

	' Overriding the base class method to implement custom rendering settings
	Public Overrides Function RenderHtmlToPdf(ByVal htmlContent As String) As Byte()
		Dim renderer = New IronPdf.ChromePdfRenderer()
		Dim pdfDocument = renderer.RenderHtmlAsPdf(htmlContent)
		' Apply a prominent watermark to the PDF document
		pdfDocument.ApplyWatermark("<h2 style='color:red; font-size: 60px; opacity: 0.5; text-shadow: 2px 2px 5px grey;'>SAMPLE</h2>", 30, IronPdf.Editing.VerticalAlignment.Middle, IronPdf.Editing.HorizontalAlignment.Center)
		' Return the binary data of the PDF document
		Return pdfDocument.BinaryData
	End Function
End Class
Friend Class Program
	Shared Sub Main(ByVal args() As String)
		License.LicenseKey = "License-Key"
		' HTML content to be converted to PDF
		Dim htmlContent As String = "<h1>Hello, IronPDF!</h1><p>This is a simple PDF document generated from HTML.</p>"
		' Create an instance of CustomPdfRenderer
		Dim renderer As New CustomPdfRenderer()
		' Call RenderHtmlToPdf method to generate PDF binary data
		Dim pdfData() As Byte = renderer.RenderHtmlToPdf(htmlContent)
		' Specify the file path to save the PDF
		Dim filePath As String = "f:\CustomRenderedPdf.pdf"
		' Save the binary data to a file
		File.WriteAllBytes(filePath, pdfData)
		Console.WriteLine($"PDF generated and saved to {filePath}")
	End Sub
End Class
VB   C#

We utilize IronPDF within a BasicPdfRenderer class to convert HTML to PDF, marking its RenderHtmlToPdf method as virtual to allow customization. The CustomPdfRenderer class, derived from BasicPdfRenderer, overrides this method to not only perform the conversion but also to inject a distinct, large, red watermark across the generated PDF.

Output PDF File

It is the PDF file generated by the IronPDF:

C# Virtual Keyword (How It Works For Developers): Figure 2 - Example code output utilizing the virtual method RenderHtmlToPDF from CustomPdfRendered for conversion

Conclusion

C# Virtual Keyword (How It Works For Developers): Figure 3 - IronPDF licensing page

The virtual keyword in C# is a cornerstone of object-oriented programming, enabling polymorphism and dynamic dispatch. By allowing derived classes to provide specific implementations of methods, properties, and events defined in base classes, it empowers developers to create flexible and reusable code structures. Through practical examples and understanding the relationship between virtual methods, override mechanisms and class hierarchies, developers can effectively utilize these concepts in building robust applications. Furthermore, these concepts would also help developers to use IronPDF more efficiently in their applications. You can test IronPDF without spending anything using its free trial costs $749 and upwards.