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.