{"id":30599,"date":"2020-11-10T09:30:00","date_gmt":"2020-11-10T16:30:00","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/dotnet\/?p=30599"},"modified":"2020-11-12T17:16:50","modified_gmt":"2020-11-13T00:16:50","slug":"c-9-0-on-the-record","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/dotnet\/c-9-0-on-the-record\/","title":{"rendered":"C# 9.0 on the record"},"content":{"rendered":"<h1 id=\"c-90-on-the-record\">C# 9.0 on the record<\/h2>\n<p>It&#8217;s official: C# 9.0 is out! Back in May I blogged about the C# 9.0 plans, and the following is an updated version of that post to match what we actually ended up shipping.<\/p>\n<p>With every new version of C# we strive for greater clarity and simplicity in common coding scenarios, and C# 9.0 is no exception. One particular focus this time is supporting terse and immutable representation of data shapes.<\/p>\n<h1 id=\"init-only-properties\">Init-only properties<\/h2>\n<p>Object initializers are pretty awesome. They give the client of a type a very flexible and readable format for creating an object, and they are especially great for nested object creation where a whole tree of objects is created in one go. Here&#8217;s a simple one:<\/p>\n<pre><code class=\"language-c#\">var person = new Person { FirstName = &quot;Mads&quot;, LastName = &quot;Torgersen&quot; };\r\n<\/code><\/pre>\n<p>Object initializers also free the type author from writing a lot of construction boilerplate &#8211; all they have to do is write some properties!<\/p>\n<pre><code class=\"language-c#\">public class Person\r\n{\r\n    public string? FirstName { get; set; }\r\n    public string? LastName { get; set; }\r\n}\r\n<\/code><\/pre>\n<p>The one big limitation today is that the properties have to be <em>mutable<\/em> for object initializers to work: They function by first calling the object&#8217;s constructor (the default, parameterless one in this case) and then assigning to the property setters. <strong>Init-only properties<\/strong> fix that! They introduce an <code>init<\/code> accessor that is a variant of the <code>set<\/code> accessor which can only be called during object initialization:<\/p>\n<pre><code class=\"language-c#\">public class Person\r\n{\r\n    public string? FirstName { get; init; }\r\n    public string? LastName { get; init; }\r\n}\r\n<\/code><\/pre>\n<p>With this declaration, the client code above is still legal, but any subsequent assignment to the <code>FirstName<\/code> and <code>LastName<\/code> properties is an error:<\/p>\n<pre><code class=\"language-c#\">var person = new Person { FirstName = &quot;Mads&quot;, LastName = &quot;Nielsen&quot; }; \/\/ OK\r\nperson.LastName = &quot;Torgersen&quot;; \/\/ ERROR!\r\n<\/code><\/pre>\n<p>Thus, init-only properties protect the state of the object from mutation once initialization is finished.<\/p>\n<h2 id=\"init-accessors-and-readonly-fields\">Init accessors and readonly fields<\/h2>\n<p>Because <code>init<\/code> accessors can only be called during initialization, they are allowed to mutate <code>readonly<\/code> fields of the enclosing class, just like you can in a constructor.<\/p>\n<pre><code class=\"language-c#\">public class Person\r\n{\r\n    private readonly string firstName = \"&lt;unknown&gt;\";\r\n    private readonly string lastName = \"&lt;unknown&gt;\";\r\n    \r\n    public string FirstName \r\n    { \r\n        get =&gt; firstName; \r\n        init =&gt; firstName = (value ?? throw new ArgumentNullException(nameof(FirstName)));\r\n    }\r\n    public string LastName \r\n    { \r\n        get =&gt; lastName; \r\n        init =&gt; lastName = (value ?? throw new ArgumentNullException(nameof(LastName)));\r\n    }\r\n}\r\n<\/code><\/pre>\n<h1 id=\"records\">Records<\/h2>\n<p>At the core of classic object-oriented programming is the idea that an object has strong identity and encapsulates mutable state that evolves over time. C# has always worked great for that, But sometimes you want pretty much the exact opposite, and here C#&#8217;s defaults have tended to get in the way, making things very laborious.<\/p>\n<p>If you find yourself wanting the whole object to be immutable and behave like a value, then you should consider declaring it as a <em>record<\/em>:<\/p>\n<pre><code class=\"language-c#\">public record Person\r\n{\r\n    public string? FirstName { get; init; }\r\n    public string? LastName { get; init; }\r\n}\r\n<\/code><\/pre>\n<p>A record is still a class, but the <code>record<\/code> keyword imbues it with several additional value-like behaviors. Generally speaking, records are defined by their contents, not their identity. In this regard, records are much closer to structs, but records are still reference types.<\/p>\n<p>While records can be mutable, they are primarily built for better supporting immutable data models.<\/p>\n<h2 id=\"with-expressions\">With-expressions<\/h2>\n<p>When working with immutable data, a common pattern is to create new values from existing ones to represent a new state. For instance, if our person were to change their last name we would represent it as a new object that&#8217;s a copy of the old one, except with a different last name. This technique is often referred to as <em>non-destructive mutation<\/em>. Instead of representing the person <em>over time<\/em>, the record represents the person&#8217;s state <em>at a given time<\/em>.  To help with this style of programming, records allow for a new kind of expression; the <code>with<\/code>-expression:<\/p>\n<pre><code class=\"language-c#\">var person = new Person { FirstName = &quot;Mads&quot;, LastName = &quot;Nielsen&quot; };\r\nvar otherPerson = person with { LastName = &quot;Torgersen&quot; };\r\n<\/code><\/pre>\n<p>With-expressions use object initializer syntax to state what&#8217;s different in the new object from the old object. You can specify multiple properties.<\/p>\n<p>The with-expression works by actually copying the full state of the old object into a new one, then mutating it according to the object initializer. This means that properties must have an <code>init<\/code> or <code>set<\/code> accessor to be changed in a with-expression.<\/p>\n<h2 id=\"value-based-equality\">Value-based equality<\/h2>\n<p>All objects inherit a virtual <code>Equals(object)<\/code> method from the <code>object<\/code> class. This is used as the basis for the <code>Object.Equals(object, object)<\/code> static method when both parameters are non-null.  Structs override this to have &quot;value-based equality&quot;, comparing each field of the struct by calling <code>Equals<\/code> on them recursively. Records do the same.  This means that in accordance with their &quot;value-ness&quot; two record objects can be equal to one another without being the <em>same<\/em> object. For instance if we modify the last name of the modified person back again:<\/p>\n<pre><code class=\"language-c#\">var originalPerson = otherPerson with { LastName = &quot;Nielsen&quot; };\r\n<\/code><\/pre>\n<p>We would now have <code>ReferenceEquals(person, originalPerson)<\/code> = false (they aren&#8217;t the same object) but <code>Equals(person, originalPerson)<\/code> = true (they have the same value). Along with the value-based <code>Equals<\/code> there&#8217;s also a value-based <code>GetHashCode()<\/code> override to go along with it. Additionally, records implement <code>IEquatable&lt;T&gt;<\/code> and overload the <code>==<\/code> and <code>!=<\/code> operators, so that the value-based behavior shows up consistently across all those different equality mechanisms.<\/p>\n<p>Value equality and mutability don&#8217;t always mesh well. One problem is that changing values could cause the result of <code>GetHashCode<\/code> to change over time, which is unfortunate if the object is stored in a hash table! We don&#8217;t disallow mutable records, but we discourage them unless you have thought through the consequences!<\/p>\n<h2 id=\"inheritance\">Inheritance<\/h2>\n<p>Records can inherit from other records:<\/p>\n<pre><code class=\"language-c#\">public record Student : Person\r\n{\r\n    public int ID;\r\n}\r\n<\/code><\/pre>\n<p>With-expressions and value equality work well with record inheritance, in that they take the whole runtime object into account, not just the type that it&#8217;s statically known by. Say that I create a <code>Student<\/code> but store it in a <code>Person<\/code> variable:<\/p>\n<pre><code class=\"language-c#\">Person student = new Student { FirstName = &quot;Mads&quot;, LastName = &quot;Nielsen&quot;, ID = 129 };\r\n<\/code><\/pre>\n<p>A with-expression will still copy the whole object and keep the runtime type:<\/p>\n<pre><code class=\"language-c#\">var otherStudent = student with { LastName = &quot;Torgersen&quot; };\r\nWriteLine(otherStudent is Student); \/\/ true\r\n<\/code><\/pre>\n<p>In the same manner, value equality makes sure the two objects have the same runtime type, and then compares all their state:<\/p>\n<pre><code class=\"language-c#\">Person similarStudent = new Student { FirstName = &quot;Mads&quot;, LastName = &quot;Nielsen&quot;, ID = 130 };\r\nWriteLine(student != similarStudent); \/\/true, since ID's are different\r\n<\/code><\/pre>\n<h2 id=\"positional-records\">Positional records<\/h2>\n<p>Sometimes it&#8217;s useful to have a more positional approach to a record, where its contents are given via constructor arguments, and can be extracted with positional deconstruction.  It&#8217;s perfectly possible to specify your own constructor and deconstructor in a record:<\/p>\n<pre><code class=\"language-c#\">public record Person \r\n{ \r\n    public string FirstName { get; init; } \r\n    public string LastName { get; init; }\r\n    public Person(string firstName, string lastName) \r\n      =&gt; (FirstName, LastName) = (firstName, lastName);\r\n    public void Deconstruct(out string firstName, out string lastName) \r\n      =&gt; (firstName, lastName) = (FirstName, LastName);\r\n}\r\n<\/code><\/pre>\n<p>But there&#8217;s a much shorter syntax for expressing exactly the same thing (modulo casing of parameter names):<\/p>\n<pre><code class=\"language-c#\">public record Person(string FirstName, string LastName);\r\n<\/code><\/pre>\n<p>This declares the public init-only auto-properties <em>and<\/em> the constructor <em>and<\/em> the deconstructor, so that you can write:<\/p>\n<pre><code class=\"language-c#\">var person = new Person(&quot;Mads&quot;, &quot;Torgersen&quot;); \/\/ positional construction\r\nvar (f, l) = person;                        \/\/ positional deconstruction\r\n<\/code><\/pre>\n<p>If you don&#8217;t like the generated auto-property you can define your own property of the same name instead, and the generated constructor and deconstructor will just use that one. In this case, the parameter is in scope for you to use for initialization. Say, for instance, that you&#8217;d rather have the <code>FirstName<\/code> be a protected property:<\/p>\n<pre><code class=\"language-c#\">public record Person(string FirstName, string LastName)\r\n{\r\n    protected string FirstName { get; init; } = FirstName; \r\n}\r\n<\/code><\/pre>\n<p>A positional record can call a base constructor like this:<\/p>\n<pre><code class=\"language-c#\">public record Student(string FirstName, string LastName, int ID) : Person(FirstName, LastName);\r\n<\/code><\/pre>\n<h1 id=\"top-level-programs\">Top-level programs<\/h2>\n<p>Writing a simple program in C# requires a remarkable amount of boilerplate code:<\/p>\n<pre><code class=\"language-c#\">using System;\r\nclass Program\r\n{\r\n    static void Main()\r\n    {\r\n        Console.WriteLine(&quot;Hello World!&quot;);\r\n    }\r\n}\r\n<\/code><\/pre>\n<p>This is not only overwhelming for language beginners, but clutters up the code and adds levels of indentation.  In C# 9.0 you can just write your main program at the top level instead:<\/p>\n<pre><code class=\"language-c#\">using System;\r\n\r\nConsole.WriteLine(&quot;Hello World!&quot;);\r\n<\/code><\/pre>\n<p>Any statement is allowed. The program has to occur after the <code>using<\/code>s and before any type or namespace declarations in the file, and you can only do this in one file, just as you can have only one <code>Main<\/code> method today.  If you want to <code>return<\/code> a status code you can do that. If you want to <code>await<\/code> things you can do that. And if you want to access command line arguments, <code>args<\/code> is available as a &quot;magic&quot; parameter.<\/p>\n<pre><code class=\"language-c#\">using static System.Console;\r\nusing System.Threading.Tasks;\r\n\r\nWriteLine(args[0]);\r\nawait Task.Delay(1000);\r\nreturn 0;\r\n<\/code><\/pre>\n<p>Local functions are a form of statement and are also allowed in the top level program. It is an error to call them from anywhere outside of the top level statement section.<\/p>\n<h1 id=\"improved-pattern-matching\">Improved pattern matching<\/h2>\n<p>Several new kinds of patterns have been added in C# 9.0. Let&#8217;s look at them in the context of this code snippet from the <a href=\"https:\/\/docs.microsoft.com\/en-us\/dotnet\/csharp\/tutorials\/pattern-matching\">pattern matching tutorial<\/a>:<\/p>\n<pre><code class=\"language-c#\">public static decimal CalculateToll(object vehicle) =&gt;\r\n    vehicle switch\r\n    {\r\n       ...\r\n       \r\n        DeliveryTruck t when t.GrossWeightClass &gt; 5000 =&gt; 10.00m + 5.00m,\r\n        DeliveryTruck t when t.GrossWeightClass &lt; 3000 =&gt; 10.00m - 2.00m,\r\n        DeliveryTruck _ =&gt; 10.00m,\r\n\r\n        _ =&gt; throw new ArgumentException(&quot;Not a known vehicle type&quot;, nameof(vehicle))\r\n    };\r\n<\/code><\/pre>\n<h2 id=\"simple-type-patterns\">Simple type patterns<\/h2>\n<p>Previously, a type pattern needs to declare an identifier when the type matches &#8211; even if that identifier is a discard <code>_<\/code>, as in <code>DeliveryTruck _<\/code> above. But now you can just write the type:<\/p>\n<pre><code class=\"language-c#\">DeliveryTruck =&gt; 10.00m,\r\n<\/code><\/pre>\n<h2 id=\"relational-patterns\">Relational patterns<\/h2>\n<p>C# 9.0 introduces patterns corresponding to the relational operators <code>&lt;<\/code>, <code>&lt;=<\/code> and so on. So you can now write the <code>DeliveryTruck<\/code> part of the above pattern as a nested switch expression:<\/p>\n<pre><code class=\"language-c#\">DeliveryTruck t when t.GrossWeightClass switch\r\n{\r\n    &gt; 5000 =&gt; 10.00m + 5.00m,\r\n    &lt; 3000 =&gt; 10.00m - 2.00m,\r\n    _ =&gt; 10.00m,\r\n},\r\n<\/code><\/pre>\n<p>Here <code>&gt; 5000<\/code> and <code>&lt; 3000<\/code> are relational patterns.<\/p>\n<h2 id=\"logical-patterns\">Logical patterns<\/h2>\n<p>Finally you can combine patterns with logical operators <code>and<\/code>, <code>or<\/code> and <code>not<\/code>, spelled out as words to avoid confusion with the operators used in expressions. For instance, the cases of the nested switch above could be put into ascending order like this:<\/p>\n<pre><code class=\"language-c#\">DeliveryTruck t when t.GrossWeightClass switch\r\n{\r\n    &lt; 3000 =&gt; 10.00m - 2.00m,\r\n    &gt;= 3000 and &lt;= 5000 =&gt; 10.00m,\r\n    &gt; 5000 =&gt; 10.00m + 5.00m,\r\n},\r\n<\/code><\/pre>\n<p>The middle case there uses <code>and<\/code> to combine two relational patterns and form a pattern representing an interval.  A common use of the <code>not<\/code> pattern will be applying it to the <code>null<\/code> constant pattern, as in <code>not null<\/code>. For instance we can split the handling of unknown cases depending on whether they are null:<\/p>\n<pre><code class=\"language-c#\">not null =&gt; throw new ArgumentException($&quot;Not a known vehicle type: {vehicle}&quot;, nameof(vehicle)),\r\nnull =&gt; throw new ArgumentNullException(nameof(vehicle))\r\n<\/code><\/pre>\n<p>Also <code>not<\/code> is going to be convenient in if-conditions containing is-expressions where, instead of unwieldy double parentheses:<\/p>\n<pre><code class=\"language-c#\">if (!(e is Customer)) { ... }\r\n<\/code><\/pre>\n<p>You can just say<\/p>\n<pre><code class=\"language-c#\">if (e is not Customer) { ... }\r\n<\/code><\/pre>\n<p>And in fact, in an <code>is not<\/code> expression like that we allow you to name the <code>Customer<\/code> for subsequent use:<\/p>\n<pre><code class=\"language-c#\">if (e is not Customer c) { throw ... } \/\/ if this branch throws or returns...\r\nvar n = c.FirstName; \/\/ ... c is definitely assigned here\r\n<\/code><\/pre>\n<h1 id=\"target-typed-new-expressions\">Target-typed <code>new<\/code> expressions<\/h2>\n<p>&quot;Target typing&quot; is a term we use for when an expression gets its type from the context of where it&#8217;s being used. For instance <code>null<\/code> and lambda expressions are always target typed.<\/p>\n<p><code>new<\/code> expressions in C# have always required a type to be specified (except for implicitly typed array expressions). In C# 9.0 you can leave out the type if there&#8217;s a clear type that the expression is being assigned to.<\/p>\n<pre><code class=\"language-c#\">Point p = new (3, 5);\r\n<\/code><\/pre>\n<p>This is particularly nice when you have a lot of repetition, such as in an array or object initializer:<\/p>\n<pre><code class=\"language-c#\">Point[] ps = { new (1, 2), new (5, 2), new (5, -3), new (1, -3) }; \r\n<\/code><\/pre>\n<h1 id=\"covariant-returns\">Covariant returns<\/h2>\n<p>It&#8217;s sometimes useful to express that a method override in a derived class has a more specific return type than the declaration in the base type. C# 9.0 allows that:<\/p>\n<pre><code class=\"language-c#\">abstract class Animal\r\n{\r\n    public abstract Food GetFood();\r\n    ...\r\n}\r\nclass Tiger : Animal\r\n{\r\n    public override Meat GetFood() =&gt; ...;\r\n}\r\n<\/code><\/pre>\n<h1 id=\"and-much-more\">And much more&#8230;<\/h2>\n<p>The best place to check out the full set of C# 9.0 features is the <a href=\"https:\/\/docs.microsoft.com\/dotnet\/csharp\/whats-new\/csharp-9\">&quot;What&#8217;s new in C# 9.0&quot; docs page<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>C# 9.0 on the record It&#8217;s official: C# 9.0 is out! Back in May I blogged about the C# 9.0 plans, and the following is an updated version of that post to match what we actually ended up shipping. With every new version of C# we strive for greater clarity and simplicity in common coding [&hellip;]<\/p>\n","protected":false},"author":1379,"featured_media":58792,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[685],"tags":[],"class_list":["post-30599","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-dotnet"],"acf":[],"blog_post_summary":"<p>C# 9.0 on the record It&#8217;s official: C# 9.0 is out! Back in May I blogged about the C# 9.0 plans, and the following is an updated version of that post to match what we actually ended up shipping. With every new version of C# we strive for greater clarity and simplicity in common coding [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts\/30599","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/users\/1379"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/comments?post=30599"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts\/30599\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/media\/58792"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/media?parent=30599"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/categories?post=30599"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/tags?post=30599"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}