Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can we use Records in C# 8.0?

I have a project using .NET Standard 2.1 and .NET core 3.1 - so the C# version is 8.0

According to a few articles I found (e.g. one, two), it should be possible to define a record type using this syntax:

public class MyRecord(string Input1, int Input2);

But I get many compilation errors, as this syntax for defining a class is clearly incorrect.

Are these articles misleading?

Is the only way to use records to upgrade to C# 9.0, and therefore .NET 5.0?

like image 710
Bassie Avatar asked May 25 '21 11:05

Bassie


3 Answers

Thanks to the other 2 answers I now understand the problem I am having

My csproj contains this line

<LangVersion>latest</LangVersion>

So I am using C# 9.0, and in fact I am able to use the record keyword like this

public record MyRecord
{
    public string Input1 { get; set; }
    public int Input2 { get; set; }
}

But if I want to use the more concise syntax from my question, I would need to include IsExternalInit from PMF's answer

In fact that would let me define it as

public sealed record MyRecord(string Input1, int Input2);

Also worth noting Jon Skeet's comment that this may eventually be released to some version of 8.X

like image 109
Bassie Avatar answered Sep 18 '22 00:09

Bassie


I have a project using .NET Standard 2.1 and .NET core 3.1 - so the C# version is 8.0

Incorrect. The default C# version is 8.0, but you can use any language version you like (as long as you have the correct build tools and build SDK), simply by changing the language version. The easiest way to do this is in the csproj:

<PropertyGroup>
    <LangVersion>9.0</LangVersion>
</PropertyGroup>

There are some caveats:

  1. some features require additional type definitions which will be missing on earlier frameworks, but can be added manually or via additional nuget package references; in the case of records, this may require IsExternalInit, which PMF shows you how to define, here
  2. some features require runtime features, and can not work on earlier frameworks, such as the new default interface implementation feature
  3. you won't get any support from Microsoft - if it works, great; if it doesn't; meh

Is the only way to use records to upgrade to C# 9.0, and therefore .NET 5.0?

No; you need the .NET 5 build SDK, but you can still target .NET Core 3.1 etc.

like image 17
Marc Gravell Avatar answered Nov 09 '22 15:11

Marc Gravell


To avoid the error Predefined type 'System.Runtime.CompilerServices.IsExternalInit' is not defined or imported, just add the following code anywhere in your project:

using System.ComponentModel;

namespace System.Runtime.CompilerServices
{
    /// <summary>
    /// Reserved to be used by the compiler for tracking metadata.
    /// This class should not be used by developers in source code.
    /// This dummy class is required to compile records when targeting .NET Standard
    /// </summary>
    [EditorBrowsable(EditorBrowsableState.Never)]
    public static class IsExternalInit
    {
    }
}

Then the record types should be netstandard2.0-compliant, meaning they work also under i.e. .NET 4.8.

like image 10
PMF Avatar answered Nov 09 '22 16:11

PMF