Test in a live environment
Test in production without watermarks.
Works wherever you need it to.
In the Object-oriented landscape of C# programming, the introduction of Primary Constructors brings a new level of elegance and simplicity to the language. Primary constructors, alongside features such as intercepters and collection expressions, emerged in C# 12 as a powerful feature, offering a more concise syntax for declaring constructors with parameters. You can explore Primary constructors in depth on the Microsoft C# guide.
In this article, we'll learn how to use C# 12 Primary Constructors efficiently, also exploring their functionality, use cases, and how they transform the way developers approach class initialization.
Constructors play a pivotal role in object-oriented programming, serving as the blueprint for initializing objects. Traditionally, C# developers have used the default constructor or parameterized constructors to set up the initial state of their classes. However, the introduction of Primary Constructors adds a more streamlined approach to this essential aspect of C# development.
A Primary Constructor in C# is a concise way to declare and initialize properties directly within the class declaration. It simplifies the process of defining and assigning values to properties, offering a more declarative and readable syntax.
The syntax for a Primary Constructor involves declaring the properties directly in the class header. Let's consider a basic Person class example:
public class Person(string name, int age)
{
public string Name { get; } = name;
public int Age { get; } = age
public override string ToString() => $"Name: {Name}, Age: {Age}";
}
public class Person(string name, int age)
{
public string Name { get; } = name;
public int Age { get; } = age
public override string ToString() => $"Name: {Name}, Age: {Age}";
}
Public Class Person(String name, Integer age)
Public ReadOnly Property Name() As String = name
public Integer Age {get;} = age public override String ToString()
If True Then
Return $"Name: {Name}, Age: {Age}"
End If
End Class
In the above code snippet, the Person class has a Primary Constructor that initializes the instance member Name and instance member Age properties. The constructor parameters are declared with the class or struct name and at the time of defining public properties the parameter values are assigned to them.
public readonly struct Point(double x, double y)
{
public double X { get; } = x;
public double Y { get; } = y;
public double Magnitude => Math.Sqrt(X * X + Y * Y);
}
public readonly struct Point(double x, double y)
{
public double X { get; } = x;
public double Y { get; } = y;
public double Magnitude => Math.Sqrt(X * X + Y * Y);
}
'INSTANT VB WARNING: VB has no equivalent to the C# readonly struct:
'ORIGINAL LINE: public readonly struct Point(double x, double y)
Public Structure Point(Double x, Double y)
Public ReadOnly Property X() As Double = x
Public ReadOnly Property Y() As Double = y
Public ReadOnly Property Magnitude() As Double
Get
Return Math.Sqrt(X * X + Y * Y)
End Get
End Property
End Structure
In this example, the primary constructor for the Point struct initializes X and Y properties, showcasing how concise and expressive the syntax can be.
public class Logger(string filePath = "log.txt", LogLevel level = LogLevel.Info)
{
private readonly string _filePath = filePath;
private readonly LogLevel _level = level;
public void Log(string message)
{
// Actual logging implementation using _filePath and _level
}
}
public class Logger(string filePath = "log.txt", LogLevel level = LogLevel.Info)
{
private readonly string _filePath = filePath;
private readonly LogLevel _level = level;
public void Log(string message)
{
// Actual logging implementation using _filePath and _level
}
}
'INSTANT VB TODO TASK: The following line contains an assignment within expression that was not extracted by Instant VB:
'ORIGINAL LINE: public class Logger(string filePath = "log.txt", LogLevel level = LogLevel.Info)
Public Class Logger(String filePath = "log.txt", LogLevel level = LogLevel.Info)
Private ReadOnly _filePath As String = filePath
Private ReadOnly _level As LogLevel = level
Public Sub Log(ByVal message As String)
' Actual logging implementation using _filePath and _level
End Sub
End Class
Here, the primary constructor for the Logger class provides default values for filePath and level, making it flexible and easy to use while maintaining configurability.
public interface IService
{
Distance GetDistance();
}
public class ExampleController(IService service) : ControllerBase
{
public ActionResult<Distance> Get() => service.GetDistance();
}
public interface IService
{
Distance GetDistance();
}
public class ExampleController(IService service) : ControllerBase
{
public ActionResult<Distance> Get() => service.GetDistance();
}
Public Interface IService
Function GetDistance() As Distance
End Interface
Public Class ExampleController(IService service)
Inherits ControllerBase
Public Function [Get]() As ActionResult(Of Distance)
Return service.GetDistance()
End Function
End Class
Primary constructors suit dependency injection scenarios. In this example, a controller class indicates its dependencies, enhancing maintainability and facilitating unit testing.
public abstract class Shape(double width, double height)
{
public double Width { get; } = width;
public double Height { get; } = height;
public abstract double CalculateArea();
}
public class Rectangle(double width, double height) : Shape(width, height)
{
public override double CalculateArea() => Width * Height;
}
public class Circle : Shape
{
public Circle(double radius) : base(radius * 2, radius * 2) { }
public override double CalculateArea() => Math.PI * Math.Pow(Width / 2, 2);
}
public abstract class Shape(double width, double height)
{
public double Width { get; } = width;
public double Height { get; } = height;
public abstract double CalculateArea();
}
public class Rectangle(double width, double height) : Shape(width, height)
{
public override double CalculateArea() => Width * Height;
}
public class Circle : Shape
{
public Circle(double radius) : base(radius * 2, radius * 2) { }
public override double CalculateArea() => Math.PI * Math.Pow(Width / 2, 2);
}
Public MustInherit Class Shape(Double width, Double height)
Public ReadOnly Property Width() As Double = width
Public ReadOnly Property Height() As Double = height
Public MustOverride Function CalculateArea() As Double
End Class
Public Class Rectangle(Double width, Double height)
Inherits Shape(width, height)
Public Overrides Function CalculateArea() As Double
Return Width * Height
End Function
End Class
Public Class Circle
Inherits Shape
Public Sub New(ByVal radius As Double)
MyBase.New(radius * 2, radius * 2)
End Sub
Public Overrides Function CalculateArea() As Double
Return Math.PI * Math.Pow(Width / 2, 2)
End Function
End Class
In this example, the primary constructor in the Shape class forms the foundation for a geometric shape hierarchy. Subclasses like Rectangle and Circle leverage the primary constructor for consistent initialization. The Rectangle class itself declares the primary constructor and passes the captured primary constructor parameters to the Shape class primary parameters. The Circle class showcases flexibility by defining its constructor within the whole class and then passing its parameters as default values for the Shape constructor using the base keyword.
IronPDF is a versatile C# library that empowers developers to create, manipulate, and convert PDF files effortlessly. Whether you're generating invoices, reports, or any other document, IronPDF allows you to seamlessly convert HTML content into polished and professional PDFs directly within your C# application.
To incorporate IronPDF into your C# project, begin by installing the IronPDF NuGet package. Execute the following command in your Package Manager Console:
Install-Package IronPdf
Alternatively, locate "IronPDF" in the NuGet Package Manager and proceed with the installation from there.
Creating a PDF using IronPDF is a streamlined process. Consider the following example:
var htmlContent = "<html><body><h1>Hello, IronPDF!</h1></body></html>";
// Create a new PDF document
var pdfDocument = new IronPdf.ChromePdfRenderer();
pdfDocument.RenderHtmlAsPdf(htmlContent).SaveAs("C:/GeneratedDocument.pdf");
var htmlContent = "<html><body><h1>Hello, IronPDF!</h1></body></html>";
// Create a new PDF document
var pdfDocument = new IronPdf.ChromePdfRenderer();
pdfDocument.RenderHtmlAsPdf(htmlContent).SaveAs("C:/GeneratedDocument.pdf");
Dim htmlContent = "<html><body><h1>Hello, IronPDF!</h1></body></html>"
' Create a new PDF document
Dim pdfDocument = New IronPdf.ChromePdfRenderer()
pdfDocument.RenderHtmlAsPdf(htmlContent).SaveAs("C:/GeneratedDocument.pdf")
In this example, IronPDF is utilized to render HTML content into a PDF document, subsequently saved to the specified location. For more details on creating and manipulating PDFs in C#, please visit this complete tutorial link, and to explore more please visit this documentation page.
C# Primary Constructors offer a declarative and streamlined approach to initializing class properties directly within the class declaration. Let's explore whether this elegant feature can be seamlessly integrated with IronPDF.
While C# Primary Constructors are primarily a language feature focused on class initialization, their direct integration with IronPDF may not be a common use case. IronPDF's core functionality lies in the generation and manipulation of PDF documents, and the specifics of class initialization might not directly align with this workflow.
However, developers can leverage C# Primary Constructors when defining custom classes or structures related to IronPDF configurations or data models. For instance, if your application requires a specific class structure to manage PDF-related settings or configurations, C# Primary Constructors can be a valuable tool for initializing these classes concisely.
public class PdfGenerationSettings(string title, bool includeHeader, bool includeFooter)
{
public string Title { get; } = title;
public bool IncludeHeader { get; } = includeHeader;
public bool IncludeFooter { get; } = includeFooter;
// Additional properties...
}
// Usage with IronPDF
var pdfSettings = new PdfGenerationSettings("My PDF Title", true, false);
var renderOptions = new ChromePdfRenderOptions();
// Apply settings from PdfGenerationSettings
renderOptions.PaperSize = IronPdf.Rendering.PdfPaperSize.A4;
renderOptions.MarginTop = 20;
renderOptions.MarginBottom = 20;
renderOptions.MarginLeft = 10;
renderOptions.MarginRight = 10;
renderOptions.Title = pdfSettings.Title ?? string.Empty;
if (pdfSettings.IncludeHeader)
{
renderOptions.TextHeader = new TextHeaderFooter
{
CenterText = "Page {page} of {total-pages}",
DrawDividerLine = true
};
}
var pdfDocument = new IronPdf.ChromePdfRenderer();
pdfDocument.RenderingOptions = renderOptions;
pdfDocument.RenderHtmlAsPdf("<html><body><h1>Hello, IronPDF!</h1></body></html>").SaveAs("CustomizedDocument.pdf");
public class PdfGenerationSettings(string title, bool includeHeader, bool includeFooter)
{
public string Title { get; } = title;
public bool IncludeHeader { get; } = includeHeader;
public bool IncludeFooter { get; } = includeFooter;
// Additional properties...
}
// Usage with IronPDF
var pdfSettings = new PdfGenerationSettings("My PDF Title", true, false);
var renderOptions = new ChromePdfRenderOptions();
// Apply settings from PdfGenerationSettings
renderOptions.PaperSize = IronPdf.Rendering.PdfPaperSize.A4;
renderOptions.MarginTop = 20;
renderOptions.MarginBottom = 20;
renderOptions.MarginLeft = 10;
renderOptions.MarginRight = 10;
renderOptions.Title = pdfSettings.Title ?? string.Empty;
if (pdfSettings.IncludeHeader)
{
renderOptions.TextHeader = new TextHeaderFooter
{
CenterText = "Page {page} of {total-pages}",
DrawDividerLine = true
};
}
var pdfDocument = new IronPdf.ChromePdfRenderer();
pdfDocument.RenderingOptions = renderOptions;
pdfDocument.RenderHtmlAsPdf("<html><body><h1>Hello, IronPDF!</h1></body></html>").SaveAs("CustomizedDocument.pdf");
Public Class PdfGenerationSettings(String title, Boolean includeHeader, Boolean includeFooter)
Public ReadOnly Property Title() As String = title
Public ReadOnly Property IncludeHeader() As Boolean = includeHeader
Public ReadOnly Property IncludeFooter() As Boolean = includeFooter
' Additional properties...
End Class
' Usage with IronPDF
Private pdfSettings = New PdfGenerationSettings("My PDF Title", True, False)
Private renderOptions = New ChromePdfRenderOptions()
' Apply settings from PdfGenerationSettings
renderOptions.PaperSize = IronPdf.Rendering.PdfPaperSize.A4
renderOptions.MarginTop = 20
renderOptions.MarginBottom = 20
renderOptions.MarginLeft = 10
renderOptions.MarginRight = 10
renderOptions.Title = If(pdfSettings.Title, String.Empty)
If pdfSettings.IncludeHeader Then
renderOptions.TextHeader = New TextHeaderFooter With {
.CenterText = "Page {page} of {total-pages}",
.DrawDividerLine = True
}
End If
Dim pdfDocument = New IronPdf.ChromePdfRenderer()
pdfDocument.RenderingOptions = renderOptions
pdfDocument.RenderHtmlAsPdf("<html><body><h1>Hello, IronPDF!</h1></body></html>").SaveAs("CustomizedDocument.pdf")
In this example, the PdfGenerationSettings class utilizes a C# Primary Constructor to initialize properties related to PDF generation settings. Later that can be used to figure out which rendering options to add and which to skip. The output contains a header text and title as it was set using the primary constructor parameter.
In conclusion, Primary Constructors in C# present a refined and expressive approach to class initialization. Their declarative syntax enhances code readability, promotes immutability, and simplifies the process of creating objects with default values. Whether you're defining properties, enforcing immutability, or embracing default values, Primary Constructors empower developers to master the art of class initialization in the dynamic world of C# programming.
While the direct integration of C# Primary Constructors with IronPDF might not be the main focus, these two elements can work together harmoniously. C# Primary Constructors enhance the clarity and simplicity of class initialization, making them valuable for defining structures or configurations related to IronPDF workflows.
Leverage the power of IronPDF for robust PDF generation, and employ C# Primary Constructors where class initialization elegance is paramount. This dynamic duo empowers you to navigate the complexities of document generation with creativity and efficiency in the vibrant world of C# programming.
IronPDF offers a free trial and its lite license starts from $749.
9 .NET API products for your office documents