What's Coming in C# 8.0? Records

Again, before I go any further, I would like to point out that as I'm writing this, the feature-set for C# 8.0 still hasn't been decided. This means that information written here is subject to change.

One of the new features being proposed in C# 8.0 is to introduce Records. Records are a new, simplified declaration form for C# class and struct types that combine the benefits of a number of simpler features. Essentially, Records are a way to create very lightweight classes that are just a collection of fields (POCO).

The Records syntax should allow implementation of these classes and structs with absolute minimum code:

public record BlogPost(string Slug, string Title, string Body, DateTime DatePublished);

This would be expanded out to a much larger class that also implements IEquatable.

using System;

public class BlogPost : IEquatable<BlogPost>
{
    public string Slug { get; }
    public string Title { get; }
    public string Body { get; }
    public DateTime DatePublished { get; }

    public BlogPost(string Slug, string Title, string Body, DateTime DatePublished)
    {
        this.Slug = Slug;
        this.Title = Title;
        this.Body = Body;
        this.DatePublished = DatePublished;
    }

    public bool Equals(BlogPost other)
    {
        return Equals(Slug, other.Slug) && Equals(Title, other.Title) && Equals(Body, other.Body) && Equals(DatePublished, other.DatePublished);
    }

    public override bool Equals(object other)
    {
        return (other as BlogPost)?.Equals(this) == true;
    }

    public override int GetHashCode()
    {
        return (Slug.GetHashCode() * 17 + Title.GetHashCode() + Body.GetHashCode() + DatePublished.GetHashCode());
    }

    public void Deconstruct(out string Slug, out string Title, out string Body, out DateTime DatePublished)
    {
        Slug = this.Slug;
        Title = this.Title;
        Body = this.Body;
        DatePublished = this.DatePublished;
    }

    public BlogPost With(string Slug = this.Slug, string Title = this.Title, string Body = this.Body, DateTime DatePublished = this.DatePublished) => new BlogPost(Slug, Title, Body, DatePublished);
}

As you can see, the properties of the record are created as read-only properties with a constructor for initializing them. In addition, it also implements value equality and overrides GetHashCode correctly for use in hash-based collections, such as Dictionary and HashTable.

Apart from this, we can also see that it has implemented a Deconstruct method, for deconstructing the class into individual values with the tuple syntax:

var (Slug, Title, Body, DatePublished) = blogPost;

Lastly, we can see the implementation of the With method. This is a new introduction to the language as well. Method parameter's default argument will additionally allow referencing a class field or property using such syntax. This is particularly useful for implementing the With helper method dedicated to creating modified copies of existing immutable objects, e.g.:

var newerBlogPost = blogPost.With(DatePublished: DateTime.Now.AddDays(20));

Additionally the with expression syntax is being considered as well, as syntactic sugar, for calling this method:

var newerBlogPost = blogPost with { DatePublished = DateTime.Now.AddDays(20) };

If you want to investigate Records in more detail, I suggest you have a look at the dotnet feature proposal on GitHub, which goes into more detail about caller-receiver parameters, with-expressions, declaration syntax and much more.