A developer from the Roslyn (.NET Compiler Platform) team recently published a *draft* specification for Records & Pattern-Matching in C#. It seems that the proposed language specification is an attempt to neatly integrate these two concepts (borrowed from F#, Haskell and friends) into the C# language. For some background see:
Pattern Matching in F#
Records in F#
Pattern Matching in Haskell
Record Types
Similar to records in F#, the proposed record type (referred to as a record class) is a new type of class that makes it easier to define & maintain read-only (immutable by default) POCOs, with the compiler handling generation of:
- Private Backing Fields
- Properties (field accessors)
- Equals (override equality operator)
- Is (required by the new pattern-matching operator)
- GetHashCode
- ToString
As an example, a record type defined as follows:
public record class Student(int age: Age, string name: Name);
Would instruct the compiler to generate the following:
public class Student
{
private readonly int _age;
private readonly string _name;
public Student(int age, string name)
{
_age = age;
_name = name;
}
public int Age { get { return _age; } }
public string Name { get { return _name; } }
// new "is" operator required for "pattern-matching"
public static bool operator is( Student student, out int age, out string name)
{
age = student.Age;
name = student.Name;
return true;
}
public override bool Equals(object obj)
{
var o = obj as Student;
return !ReferenceEquals(o, null)
&& object.Equals(_age, o.Age)
&& object.Equals(_name, o.Name);
}
public override int GetHashCode()
{
int v = 1203787;
v = (v * 28341) + Age?.GetHashCode().GetValueOrDefault();
v = (v * 28341) + Name?.GetHashCode().GetValueOrDefault();
return v;
}
public override string ToString()
{
return new System.Text.StringBuilder()
.Append("Student(Age: ")
.Append(_age)
.Append(", Name: ")
.Append(_name)
.Append(")")
.ToString();
}
}
While all of this code generation and syntactic sugar will no doubt make our lives easier, the really interesting thing here is the new "is" operator.
Patterns
This part of the proposed feature will allow developers to control program flow using familiar if-is or switch statements by expressing the "shape" data must be matched to including:
- Types
- Constants
- Variables
- Wildcards
- Recursive Patterns
As an example, consider how we'd currently control program flow based on the type of a variable.
var button = control as Button;
if(button != null) button.Click();
Using a "Type Pattern" we'd be able to simplify this:
if(control is Button button) button.Click();
While this is a fairly trivial example, complex pattern matching, including switch statements & recursive patterns may revolutionize the way we write some C# programs. I understand the team is planning to publish a prototype "in a few weeks", so I'll post some real world examples of how the different types of patterns might be used.
In the meantime, if you're interested in learning more, the draft specification is available here.
Comments