in Technology by
What is Record types in C#.Net?

1 Answer

0 votes
by

C# 9.0 introduces record types, which are a reference type that provides synthesized methods to provide value semantics for equality. Records are immutable by default.

Record types make it easy to create immutable reference types in .NET. Historically, .NET types are largely classified as reference types (including classes and anonymous types) and value types (including structs and tuples). While immutable value types are recommended, mutable value types don’t often introduce errors. Value type variables hold the values so changes are made to a copy of the original data when value types are passed to methods.

There are many advantages to immutable reference types as well. These advantages are more pronounced in concurrent programs with shared data. Unfortunately, C# forced you to write quite a bit of extra code to create immutable reference types. Records provide a type declaration for an immutable reference type that uses value semantics for equality. The synthesized methods for equality and hash codes consider two records equal if their properties are all equal. Consider this definition:

public record Person
{
    public string LastName { get; }
    public string FirstName { get; }

    public Person(string first, string last) => (FirstName, LastName) = (first, last);
}

The record definition creates a Person type that contains two readonly properties: FirstName and LastName. The Person type is a reference type. If you looked at the IL, it’s a class. It’s immutable in that none of the properties can be modified once it's been created. When you define a record type, the compiler synthesizes several other methods for you:

  • Methods for value-based equality comparisons
  • Override for GetHashCode()
  • Copy and Clone members
  • PrintMembers and ToString()

Records support inheritance. You can declare a new record derived from Person as follows:

public record Teacher : Person
{
    public string Subject { get; }

    public Teacher(string first, string last, string sub)
        : base(first, last) => Subject = sub;
}

You can also seal records to prevent further derivation:

public sealed record Student : Person
{
    public int Level { get; }

    public Student(string first, string last, int level) : base(first, last) => Level = level;
}

The compiler synthesizes different versions of the methods above. The method signatures depend on if the record type is sealed and if the direct base class is object. Records should have the following capabilities:

  • Equality is value-based, and includes a check that the types match. For example, a Student can't be equal to a Person, even if the two records share the same name.
  • Records have a consistent string representation generated for you.
  • Records support copy construction. Correct copy construction must include inheritance hierarchies, and properties added by developers.
  • Records can be copied with modification. These copy and modify operations supports non-destructive mutation.

In addition to the familiar Equals overloads, operator ==, and operator !=, the compiler synthesizes a new EqualityContract property. The property returns a Type object that matches the type of the record. If the base type is object, the property is virtual. If the base type is another record type, the property is an override. If the record type is sealed, the property is sealed. The synthesized GetHashCode uses the GetHashCode from all properties and fields declared in the base type and the record type. These synthesized methods enforce value-based equality throughout an inheritance hierarchy. That means a Student will never be considered equal to a Person with the same name. The types of the two records must match as well as all properties shared among the record types being equal.

Records also have a synthesized constructor and a "clone" method for creating copies. The synthesized constructor has a single parameter of the record type. It produces a new record with the same values for all properties of the record. This constructor is private if the record is sealed, otherwise it's protected. The synthesized "clone" method supports copy construction for record hierarchies. The term "clone" is in quotes because the actual name is compiler generated. You can't create a method named Clone in a record type. The synthesized "clone" method returns the type of record being copied using virtual dispatch. The compiler adds different modifiers for the "clone" method depending on the access modifiers on the record:

  • If the record type is abstract, the "clone" method is also abstract. If the base type isn't object, the method is also override.
  • For record types that aren't abstract when the base type is object:
    • If the record is sealed, no additional modifiers are added to the "clone" method (meaning it is not virtual).
    • If the record isn't sealed, the "clone" method is virtual.
  • For record types that aren't abstract when the base type is not object:
    • If the record is sealed, the "clone" method is also sealed.
    • If the record isn't sealed, the "clone" method is override.

The result of all these rules is the equality is implemented consistently across any hierarchy of record types. Two records are equal to each other if their properties are equal and their types are the same, as shown in the following example:

var person = new Person("Bill", "Wagner");
var student = new Student("Bill", "Wagner", 11);

Console.WriteLine(student == person); // false

The compiler synthesizes two methods that support printed output: a ToString() override, and PrintMembers. The PrintMembers takes a System.Text.StringBuilder as its argument. It appends a comma-separated list of property names and values for all properties in the record type. PrintMembers calls the base implementation for any records derived from other records. The ToString() override returns the string produced by PrintMembers, surrounded by { and }. For example, the ToString() method for Student returns a string like the following code:

"Student { LastName = Wagner, FirstName = Bill, Level = 11 }"

The examples shown so far use traditional syntax to declare properties. There's a more concise form called positional records. Here are the three record types defined earlier as positional records:

public record Person(string FirstName, string LastName);

public record Teacher(string FirstName, string LastName,
    string Subject)
    : Person(FirstName, LastName);

public sealed record Student(string FirstName,
    string LastName, int Level)
    : Person(FirstName, LastName);

Related questions

0 votes
    I'm new to React with Redux and I've been working on a new web application that has some basic ... JavaScript Questions for Interview, JavaScript MCQ (Multiple Choice Questions)...
asked Apr 29, 2022 in Education by JackTerrance
0 votes
    Name different Info record types in SAP MM?...
asked Mar 14, 2021 in Technology by JackTerrance
0 votes
    What are the different data types that a standard field record name can have?...
asked Nov 11, 2020 in Technology by JackTerrance
0 votes
    What is Garbage Collection in C#.Net?...
asked Jul 27, 2021 in Technology by JackTerrance
0 votes
    What is Reflection in C#.Net?...
asked Jul 27, 2021 in Technology by JackTerrance
0 votes
    What is File Handling in C#.Net?...
asked Apr 1, 2021 in Technology by JackTerrance
0 votes
    What is Fit and finish features in C#.Net?...
asked Dec 30, 2020 in Technology by JackTerrance
0 votes
    What is Pattern matching enhancements in C#.Net?...
asked Dec 30, 2020 in Technology by JackTerrance
0 votes
    What is Top-level statements in C#.NET?...
asked Dec 30, 2020 in Technology by JackTerrance
0 votes
    What is Init only setters C#.Net?...
asked Dec 30, 2020 in Technology by JackTerrance
0 votes
    What is Default interface methods in C#.Net?...
asked Dec 30, 2020 in Technology by JackTerrance
0 votes
    What is Readonly members in C#.Net?...
asked Dec 30, 2020 in Technology by JackTerrance
0 votes
    I'm coding a basic portfolio page in ASP.NET Core Razor Pages. I want to have a contact form at ... JavaScript Questions for Interview, JavaScript MCQ (Multiple Choice Questions)...
asked Apr 9, 2022 in Education by JackTerrance
0 votes
    How do I implement a Copy menu item in a Windows application written in C#/.NET 2.0? I want to ... , JavaScript Questions for Interview, JavaScript MCQ (Multiple Choice Questions)...
asked Mar 29, 2022 in Education by JackTerrance
0 votes
    Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers. Want ... Questions for Interview, JavaScript MCQ (Multiple Choice Questions)...
asked Mar 19, 2022 in Education by JackTerrance
...