.NET HELP

C# Record Vs Class (How It Works For Developers)

Published August 11, 2024
Share:

In the world of C#, two primary structures are utilized to model and encapsulate data: classes and records. Both serve as reference types but differ significantly in their intended use, behavior, and how they handle equality. This guide will dissect these differences, providing clear examples and practical uses to aid developers in choosing the right structure for their needs. We'll also learn about the IronPDF library.

Classes in C#: The Basics

Classes have been a cornerstone of object-oriented programming in C#, designed to encapsulate data and behavior. They are reference types, meaning two class instances with the same values are considered two separate objects. This distinction is crucial when comparing two class instances; the default comparison is reference-based, not value-based.

public class Person
{
    public int Id { get; set; }
    public string FullName { get; set; }
}
public class Person
{
    public int Id { get; set; }
    public string FullName { get; set; }
}
Public Class Person
	Public Property Id() As Integer
	Public Property FullName() As String
End Class
VB   C#

In the example above, Person is a class with Id and FullName properties. Even if two Person instances have identical Id and FullName values, they are not considered equal by default because they are two different references in memory.

Records in C#: Immutable Data Structures

Introduced in C#, the record type is a newer addition aimed at simplifying the creation of immutable data structures, providing a robust alternative to traditional class structures. Unlike classes, records offer value-based equality semantics, making them ideal for data transfer objects or small data structures with little or no behavior.

public record Person(int Id, string FullName);
public record Person(int Id, string FullName);
'INSTANT VB TODO TASK: C# 'records' are not converted by Instant VB:
'public record Person(int Id, string FullName)
VB   C#

In the above example, the record definition is more succinct, reducing boilerplate code. Records automatically support nondestructive mutation and value-based comparison. Two record instances with the same values are considered equal, aligning with value semantics.

Practical Uses: When to Use Record vs. Class

Choosing between a class and a record, or other data structures in C#, depends on the complexity of the data you're modeling and the behaviors required by your application. Classes are specifically designed for complex data structure, accommodating behaviors (methods) and allowing for mutable instances as required. Records, on the other hand, are perfect examples of a simple data structure, designed with immutable characteristics and value-based equality, ideal for data that remains constant after creation.

Classes are ideal when your data structure requires encapsulating data and behaviors or when you need to manipulate the data after its creation. This flexibility makes classes a go-to for most traditional object-oriented programming scenarios and when creating complex data structures.

Records shine in scenarios where data immutability is crucial or when you're dealing with simple data structures that primarily serve as data containers. Their built-in value-based equality and concise syntax make them excellent for data transfer objects or value objects.

Value Types and Reference Types

Understanding the difference between value type and reference type in C# is vital. Classes are reference types, meaning variables hold a reference to the actual data in memory. This characteristic leads to the default reference-based equality comparison.

Records, while also reference types, emulate value semantics through their built-in value-based equality, making them behave somewhat like value types in comparisons.

Code Examples: Implementing Classes and Records

Let's implement a class and a record to highlight the differences in syntax and behavior.

Class Implementation:

public class Product
{
    public int Id { get; set; }
    public string Name { get; set; }

    public Product(int id, string name)
    {
        Id = id;
        Name = name;
    }
}
public class Product
{
    public int Id { get; set; }
    public string Name { get; set; }

    public Product(int id, string name)
    {
        Id = id;
        Name = name;
    }
}
Public Class Product
	Public Property Id() As Integer
	Public Property Name() As String

	Public Sub New(ByVal id As Integer, ByVal name As String)
		Me.Id = id
		Me.Name = name
	End Sub
End Class
VB   C#

Record Implementation:

public record Product(int Id, string Name);
public record Product(int Id, string Name);
'INSTANT VB TODO TASK: C# 'records' are not converted by Instant VB:
'public record Product(int Id, string Name)
VB   C#

Notice the brevity and simplicity of the record implementation. The record automatically generates the constructor, properties, and methods for value-based equality.

Understanding Equality: Reference vs. Value

The core difference between class and record types in C# indeed lies in how they handle equality:

  1. Classes use reference equality by default, meaning two instances are equal if they point to the same memory location.

  2. Records use value equality by default, considering two instances equal if their properties have the same values.

Reference Equality Example (Class)

public class Person
{
    public int Id { get; set; }
    public string Name { get; set; }
}

var classInstance1 = new Person { Id = 1, Name = "Iron Software" };
var classInstance2 = new Person { Id = 1, Name = "Iron Software" };
Console.WriteLine(classInstance1 == classInstance2); // Outputs: False
public class Person
{
    public int Id { get; set; }
    public string Name { get; set; }
}

var classInstance1 = new Person { Id = 1, Name = "Iron Software" };
var classInstance2 = new Person { Id = 1, Name = "Iron Software" };
Console.WriteLine(classInstance1 == classInstance2); // Outputs: False
Public Class Person
	Public Property Id() As Integer
	Public Property Name() As String
End Class

Private classInstance1 = New Person With {
	.Id = 1,
	.Name = "Iron Software"
}
Private classInstance2 = New Person With {
	.Id = 1,
	.Name = "Iron Software"
}
Console.WriteLine(classInstance1 = classInstance2) ' Outputs: False
VB   C#

Two instances of a class with the same property values are not considered equal because they are different objects in memory.

Value Equality Example

public record Person(int Id, string Name);

var recordInstance1 = new Person(1, "Iron Software");
var recordInstance2 = new Person(1, "Iron Software");
Console.WriteLine(recordInstance1 == recordInstance2); // Outputs: True
public record Person(int Id, string Name);

var recordInstance1 = new Person(1, "Iron Software");
var recordInstance2 = new Person(1, "Iron Software");
Console.WriteLine(recordInstance1 == recordInstance2); // Outputs: True
'INSTANT VB TODO TASK: C# 'records' are not converted by Instant VB:
'public record Person(int Id, string Name)

Private recordInstance1 = New Person(1, "Iron Software")
Private recordInstance2 = New Person(1, "Iron Software")
Console.WriteLine(recordInstance1 = recordInstance2) ' Outputs: True
VB   C#

Two instances of a record with the same property values are considered equal by default.

Advanced Features: Records

Records come with several advanced features that cater to the need for immutable data structures and value-based equality. The with expression allows for creating a new record instance by copying an existing record but with some properties modified, demonstrating nondestructive mutation.

Nondestructive Mutation with Records:

var originalRecord = new Person(1, "Doe");
var modifiedRecord = originalRecord with { Name = "Iron Developer" };
var originalRecord = new Person(1, "Doe");
var modifiedRecord = originalRecord with { Name = "Iron Developer" };
Dim originalRecord = New Person(1, "Doe")
'INSTANT VB TODO TASK: C# 'with expressions' are not converted by Instant VB:
'var modifiedRecord = originalRecord with { Name = "Iron Developer" }
VB   C#

This feature is handy when working with immutable data structures, as it provides a way to "modify" an instance without altering the original data.

Introduction of IronPDF Library

IronPDF webpage

IronPDF is a PDF library for .NET developers, offering a comprehensive solution for creating, editing, and managing PDF documents directly within .NET applications. It simplifies the PDF generation process by allowing developers to convert HTML into PDFs, CSS, JavaScript, and images into PDFs. IronPDF supports a variety of .NET frameworks and project types, including web, desktop, and console applications, across multiple operating systems such as Windows, Linux, and macOS.

Beyond PDF creation, IronPDF provides capabilities for editing PDFs, setting properties and security, working with PDF forms, and extracting content. It's designed to meet the needs of developers looking for a reliable tool to integrate PDF functionality into their .NET projects.

Code Example

Creating a PDF in C# using IronPDF can be achieved with both classes and records. Below, are examples of both approaches to generate a simple PDF document. The primary difference between classes and records in C# lies in their intended use: classes are mutable by default and designed for traditional object-oriented programming, while records are immutable and designed for value-based programming, making them ideal for data modeling.

Using a Class

In this example, we'll define a PdfGenerator class that contains a method to create a PDF from a given HTML string.

using IronPdf;

public class PdfGenerator
{
    public string HtmlContent { get; set; }

    public PdfGenerator(string htmlContent)
    {
        HtmlContent = htmlContent;
    }

    public void GeneratePdf(string filePath)
    {
        var renderer = new ChromePdfRenderer();
        var pdfDocument = renderer.RenderHtmlAsPdf(HtmlContent);
        pdfDocument.SaveAs(filePath);
    }
}

class Program
{
    public static void Main(string[] args)
    {
        License.LicenseKey = "License-Key";

        var generator = new PdfGenerator("<h1>Hello, World from Class!</h1>");
        generator.GeneratePdf("ClassExample.pdf");
    }
}
using IronPdf;

public class PdfGenerator
{
    public string HtmlContent { get; set; }

    public PdfGenerator(string htmlContent)
    {
        HtmlContent = htmlContent;
    }

    public void GeneratePdf(string filePath)
    {
        var renderer = new ChromePdfRenderer();
        var pdfDocument = renderer.RenderHtmlAsPdf(HtmlContent);
        pdfDocument.SaveAs(filePath);
    }
}

class Program
{
    public static void Main(string[] args)
    {
        License.LicenseKey = "License-Key";

        var generator = new PdfGenerator("<h1>Hello, World from Class!</h1>");
        generator.GeneratePdf("ClassExample.pdf");
    }
}
Imports IronPdf

Public Class PdfGenerator
	Public Property HtmlContent() As String

	Public Sub New(ByVal htmlContent As String)
		Me.HtmlContent = htmlContent
	End Sub

	Public Sub GeneratePdf(ByVal filePath As String)
		Dim renderer = New ChromePdfRenderer()
		Dim pdfDocument = renderer.RenderHtmlAsPdf(HtmlContent)
		pdfDocument.SaveAs(filePath)
	End Sub
End Class

Friend Class Program
	Public Shared Sub Main(ByVal args() As String)
		License.LicenseKey = "License-Key"

		Dim generator = New PdfGenerator("<h1>Hello, World from Class!</h1>")
		generator.GeneratePdf("ClassExample.pdf")
	End Sub
End Class
VB   C#

Output:

Outputted PDF from the class example

Using a Record

In contrast, a record in C# is immutable after initialization. Here's how you could achieve a similar outcome with a record, utilizing with-expressions for modifications, which essentially return a new instance of the record with the desired changes.

using IronPdf;

public record PdfGeneratorRecord(string HtmlContent)
{
    public void GeneratePdf(string filePath)
    {
        var renderer = new ChromePdfRenderer();
        var pdfDocument = renderer.RenderHtmlAsPdf(this.HtmlContent);
        pdfDocument.SaveAs(filePath);
    }
}

class Program
{
    public static void Main(string[] args)
    {
        License.LicenseKey = "License-Key";

        var recordGenerator = new PdfGeneratorRecord("<h1>Hello, World from Record!</h1>");
        recordGenerator.GeneratePdf("RecordExample.pdf");
    }
}
using IronPdf;

public record PdfGeneratorRecord(string HtmlContent)
{
    public void GeneratePdf(string filePath)
    {
        var renderer = new ChromePdfRenderer();
        var pdfDocument = renderer.RenderHtmlAsPdf(this.HtmlContent);
        pdfDocument.SaveAs(filePath);
    }
}

class Program
{
    public static void Main(string[] args)
    {
        License.LicenseKey = "License-Key";

        var recordGenerator = new PdfGeneratorRecord("<h1>Hello, World from Record!</h1>");
        recordGenerator.GeneratePdf("RecordExample.pdf");
    }
}
Imports IronPdf

'INSTANT VB TODO TASK: C# 'records' are not converted by Instant VB:
'public record PdfGeneratorRecord(string HtmlContent)
'{
'	public void GeneratePdf(string filePath)
'	{
'		var renderer = New ChromePdfRenderer();
'		var pdfDocument = renderer.RenderHtmlAsPdf(Me.HtmlContent);
'		pdfDocument.SaveAs(filePath);
'	}
'}

Friend Class Program
	Public Shared Sub Main(ByVal args() As String)
		License.LicenseKey = "License-Key"

		Dim recordGenerator = New PdfGeneratorRecord("<h1>Hello, World from Record!</h1>")
		recordGenerator.GeneratePdf("RecordExample.pdf")
	End Sub
End Class
VB   C#

Output:

Outputted PDF from the record example

These examples illustrate how to generate a PDF file using IronPDF with both a class and a record in C#. The choice between using a class or a record depends on your specific needs: if you need objects that are going to be modified after creation, a class might be more appropriate. If you're dealing with data that shouldn't change once it's been created, or you appreciate the syntactical simplicity and safety of immutability, a record could be the better choice.

Conclusion

IronPDF licensing page

In conclusion, classes offer traditional object-oriented features with mutable state and reference-based equality, while records provide a modern approach to defining immutable data structures with value-based equality.

The choice between using a class or a record should be guided by the specific requirements of your application, considering factors like the need for immutability, the complexity of the data structure, and the preferred method of equality comparison. Discover IronPDF's Free Trial for those looking to integrate PDF functionality into their .NET applications, with licenses starting from $749.

< PREVIOUS
C# Sleep (How It Works For Developers)
NEXT >
MySqlclient C# (How It Works For Developers)

Ready to get started? Version: 2024.12 just released

Free NuGet Download Total downloads: 11,622,374 View Licenses >