Simple Secrets for Access to the dotnet Record Type

In C# 9.0 we received access to a great quality of life type called the record. You can read more about that from Microsoft here. Record types allowed us as dotnet programmers to skip a lot of boiler plate code, thereby saving us time and making code more readable. Wins all around!

Before record types, we might have simple data transfer objects (called DTOs) that would look something like the following:

public sealed class MyData
{
	public MyData(
		string value1,
		int value2)
	{
		Value1 = value1;
		Value2 = value2;
	}

	publc string Value1 { get; }

	publc int Value2 { get; }
}

And for a simple class with two properties… I think we can all agree that the verbosity here is just over the top. With the record type that we were given access to, we can now write it as simply as the following:

public sealed record MyData(
	string Value1,
	int value2);

All of that effectively reduced right down to one line (I personally like putting my parameters on new lines) of code! Much cleaner and much easier to maintain. Records also give us a few other benefits like ToString() and equality overrides, but those are again provided in detail by Microsoft here.

How do I access these on earlier versions?

This is a very popular question, especially because this vastly improves the quality of life for many software engineers for a pattern we are stuck with. There are some articles that explain how you can do this by adding in missing attributes, but we’ll actually explore a much less manual approach.

Step 1 – LanguageVersion to enable record types

These solutions all have one thing in common, and that’s having at least a compiler language version installed that’s high enough to target support for record types. This is because the record type itself does not require fancy language features, but is instead a marker for the compiler to generate code in a particular way.

To make this work for us, we will want to edit our project file and include the following:

<LangVersion>9.0</LangVersion>

And in theory, 9.0 will be the minimum for records but as we explore the rest of the solution you may want to change this to a higher value depending on some follow up! So keep reading to see more about this.

This should mean that your csproj file would look something like the following with the new line added to it:

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <LangVersion>9.0</LangVersion>
    <TargetFramework>net4.8</TargetFramework>
  </PropertyGroup>

</Project>

And with that setup, you can save your project and move onto the next step.

Step 2 – PolySharp for polyfilling record types

Our solution is going to be relying on an incredibly handy nuget package called PolySharp. You can check out the source repository and read all of the details here on github. This package will help us with not only with record types, but if you scroll through the github page you can see plenty of examples of this exact same pattern of syntactic sugar being taken care of for us.

Right, so our next move is to get PolySharp nuget package added. You can do this through the dotnet console commands or in Visual Studio through the package manager. And realistically, at this point once it’s installed you have done everything you need to do.

Easier with a video?

YouTube player

What’s next?

As mentioned, it’s worth giving a read through on the PolySharp page to see what other features you might be able to unlock. Personally, I am going back over many of my Unity3D projects and trying to figure out which features I can start to include. This is because Unity3D is (at the time of writing) much further behind on features in C# as they move forward on their architecture.

I would have loved to include a .NET Fiddle for this, but it turns out that I could not get it to work in the web app. However, I instead just pushed up a set of example code that you can check out here on github. Have a read through, and if you want to try it you only need the files in the folder for the given example. It will print out the compiled runtime version as well as information about the struct!

Record Types in Earlier Versions Example - PolySharp Nuget Package
The console window shows the assembly runtime as well as the output of the record ToString method

Give it a shot and it would be great to hear what success stories you have with being able to modernize your .NET apps stuck on older frameworks!

author avatar
Nick Cosentino Principal Software Engineering Manager
Principal Software Engineering Manager at Microsoft. Views are my own.

Leave a Reply