Immutability is a concept that has been widely adopted in several programming languages. C# has been patiently waiting for a dedicated feature for this, and records are here!
In this article, we will explore C# records, ratify every myth and question surrounding records and classes, delve into the C# record constructor, reflect on inheritance, and understand how private records work in .NET. Let's go!
C# Records
Ever stumbled upon a piece of code filled with boilerplate just to make a class immutable? Good news; C# records to the rescue!
What are C# Records?
C# Records are a new kind of type declaration â theyâre similar to classes, but theyâre suited for developing immutable data models out of the box. Records, to put it simply, can be summarized as Simple-Immutables-Simplified.
Consider the following Record:
public record Person(string Name, int Age);
Youâve just defined an immutable type named âPersonâ with two properties, âNameâ and âAgeâ. That was easy, wasnât it?
The Syntax of C# Records
The simple syntax of a record is yet another of its perks. Just like âclassesâ and âstructsâ, you can declare ârecordsâ with properties, methods, and events.
public record Car
{
public string Brand { get; init; }
public string Model { get; init; }
}
The âinitâ keyword ensures the properties are immutable, i.e., once assigned, they canât be changed.
But you might be wondering, what about value equality? Hereâs another cool thing about records â they bring âvalue equalityâ into play, rather than âreference equalityâ, which conventional classes use.
Delving into the Details: C# Record Types
Letâs break it down and dive deeper into the abyss of C# Record types.
Understanding the Structure of C# Record Types
Hereâs the code-example illustrating the structure and key elements of a C# Record.
public record Employee
{
public string Name { get; init; }
public string Department { get; init; }
public Employee Manager { get; init; }
}
In this case, the Employee record consists of three properties. âNameâ and âDepartmentâ are self-explanatory, but âManagerâ is a nested declaration within the Employee record â an Employee type inside Employee.
When to Use C# Records
Record in C# should be used when:
- You need a type primarily defined by its data, and this data is immutable.
- You need value equality â âAre these two things the same?â rather than âAre they the same object?â
So, isnât it splendid how records encapsulate the essence of object-oriented programming? Theyâre quite the game-changer!
C# Record vs Class: A Comprehensive Reality Check
As Coders, we grapple with design decisions every day. Such a common predicament is when to use a class and when to opt for a record in C#. The fascinating world of programming languages is full of such dilemmas, and each choice can parley into diverse results.
Distinguishing the Functionality: C# Record vs Class
Indeed, C# records and classes are akin but have distinctive behaviours, especially around immutability and equality. But how about we get our hands dirty and write some code to unravel the differences?
public class CountryClass
{
public string Name { get; set; }
public string Continent { get; set; }
}
public record CountryRecord(string Name, string Continent);
CountryClass country1 = new CountryClass { Name = "Germany", Continent = "Europe" };
CountryClass country2 = new CountryClass { Name = "Germany", Continent = "Europe" };
Console.WriteLine(country1 == country2); // Output: False
The comparison of country1 & country2 returns false even though they have identical properties. Itâs because classes in C# compare references, not the contents.
Now, letâs contrast this with records:
CountryRecord countryRecord1 = new CountryRecord("Germany", "Europe");
CountryRecord countryRecord2 = new CountryRecord("Germany", "Europe");
Console.WriteLine(countryRecord1 == countryRecord2); // Output: True
Wowza, it returns true
. So, records in C# are different â they factor in the contents for comparison, not just reference! They are immutable and possess value semantics. Ainât that nifty?
Realistic Use-Case Scenario: C# Record vs Class
Remember our old friend, the Product Catalogue, in an e-commerce application? Hereâs where our recently learned knowledge comes into play. Letâs consider two classes, ProductClass and ProductRecord:
public class ProductClass
{
public string ProductName { get; set; }
public string Description { get; set; }
public decimal Price { get; set; }
//...more properties
}
public record ProductRecord(string ProductName, string Description, decimal Price);
For largely immutable entities like a product catalogue, employing records makes sense. You get a concise, immutable object with equal-to and copy semantics out of the box. You can also update properties using the with
keyword while retaining the immutability:
var baseProduct = new ProductRecord("Book", "It's a book, duh!", 10m);
var discountedProduct = baseProduct with { Price = 9m };
However, when objects require mutable state, classes still emerge victoriously. Imagine a Shopping Cart class in the same e-commerce application. You continually add, remove items, indicating a frequent change of state. Leveraging classes here is more fitting.
Each tool has its place. Isnât that the philosophy of good programming?
Recorder C#: Automated Testing
We, coders, often find ourselves in a bind when dealing with UI tests. Wouldnât it be great if we could just record our browser interactions and convert them into C# code for WebDriver-based UI tests? Well, thatâs precisely what Recorder C# does for you!
var driver = new ChromeDriver();
var recorder = new Recorder(driver);
recorder.Start();
driver.Navigate().GoToUrl("http://www.yoursite.com");
//...do your testing
recorder.Stop();
The Start
method tells the recorder to start recording and the Stop
method to stop. The rest is all your interactions with the UI!
Mastering the C# Record Constructor
A constructorâs primary function is to initialize the object of a class. But in C# records, a constructor does more than that!
Streamlining Constructors with C# Records
Records break the traditional mould of constructors. Just look at this tidy piece of code!
public record Employee(string Name, string Department);
Here, in merely one line of code, youâve given birth to a record with a constructor accepting two parameters and associating them to the read-only characteristics of the object. Talk about efficiency!
Crafting a C# Record Constructor
However, if your constructor requires additional logic or even validation of parameters, records can cover that too:
public record Employee
{
public Employee(string name, string department)
{
if (string.IsNullOrEmpty(name)) throw new ArgumentNullException(nameof(name));
if (string.IsNullOrEmpty(department)) throw new ArgumentNullException(nameof(department));
Name = name;
Department = department;
}
public string Name { get; }
public string Department { get; }
}
Need to validate input? You can add validation checks right inside the constructor. Itâs like having your cake and eating it too (figuratively speaking)!
Understanding C# Record Inheritance
The Concept: C# Record Inheritance
Records inherit from other records. How cool is that? Records use the keyword ârecordâ instead of âclassâ for inheritance. Take a look:
public record Vehicle
{
public string Brand { get; init; }
}
public record Truck : Vehicle
{
public int TowingCapacity { get; init; }
}
Here, âTruckâ record is inheriting from the âVehicleâ record. Talk about keeping the lineage clean!
Taking Advantage of C# Record Inheritance
Remember, records are sealed by default. If you want to allow other records to inherit from a base record, be sure to include the sealed
modifier:
public sealed record Vehicle
{
public string Brand { get; init; }
}
Itâs stunning how much thought is put into extending and improving C# towards a more immutable future!
C# Record Property: Tweaking and Modifying
Letâs shed some light on how you can tweak and modify properties in C# Records.
Blessing of Immutability: C# Record Change Property
Records in C# are immutable, but there are times when you need a copy of a record with one or more properties modified. C# Record has the âwithâ keyword for this. Magic, isnât it?
public record Person(string Name, int Age);
Person bob = new Person("Bob", 30);
Person bobTwin = bob with { Name = "Bob's Twin" }; // New person with age 30
Here, bobTwin
is a new record, based on Bob, but itâs not Bob. Mind=blown!
Decoding the Differences: C# Record vs Record Struct
To struct, or not to struct, thatâs the conundrum!
Understanding the Key Distinctions
So whatâs the brass tacks of C# Record and Record Struct? The essential difference is that by design, record class
types use reference semantics for equality while record struct
types use value semantics for equality.
Making the Right Choice: C# Record vs Record Struct
When faced with the choice between record class
and record struct
, always go for the one that fits your scenario. When in doubt, favor record class
. The semantics of a reference type better align with how data models are typically used.
Exploring Private Records in .NET
Private Records in C#: An introduction
Ever wished for private record types in C#? Your wish is C#âs command! This incredible addition of private accessibility modifier to record types makes things immeasurably simpler.
Application and Use Cases of Private Records in .NET
A private record is useful when seeking to encapsulate operations within a type, and its details play no role in its public API. This makes it an ideal candidate for implementing Data Transfer Object (DTO) patterns and encapsulating algorithms.
Congratulations, folks! Youâve made it to the end of this enthralling journey through the vast landscape of C# records. Weâve covered everything from the basics, to scenarios for usage, to comparisons with classes, and weâve even touched on C# Record Constructors, inheritance, property changes, and private records in .NET.
Now, itâs time for you to apply these concepts and take advantage of this wonderful feature of C#.
Remember, though records are awesome, theyâre not a silver bullet for all scenarios. Sometimes, classes or structs might be just what you need.
Think it through, always opt for the simplest solution that meets your need.
Top comments (4)
I ask question to Copilot. Here are the response. Could help other people.
The difference between a record class and a record struct in C# mainly revolves around whether they are reference types or value types:
Record Class:
Record Struct:
In summary, choose record classes for more complex, reference-based data structures and record structs for simpler, value-based data structure
After that, I asked :
I thought that records were immutable. Why record structs are mutable by default ?
That's a great question! While records in C# are often associated with immutability, the default mutability of record structs is due to their nature as value types.
Here's a bit more detail:
Record Classes: These are reference types and are immutable by default. This immutability is a key feature that helps ensure that the data they hold cannot be changed after creation, which is useful for creating reliable and predictable data structures.
Record Structs: These are value types and are mutable by default. This default mutability is because value types are typically used for small, simple data structures where performance is critical, and the overhead of creating new instances for every change can be significant. However, you can make record structs immutable by using the
readonly
keyword.If you want to make a record struct immutable, you can define it like this:
This way, the properties
X
andY
cannot be changed after thePoint
is created.very nice article, thx !!
But I don"t really understand why the part "Recorder C#: Automated Testing" is here (even if it is interesting)
and the end, record struc vs record class should be better explained, IMHO.
thx again anyway !! :)
Thank you :-)
Top, very nice and helpful !
Thanks for sharing. â