My proposed syntax for record types in C#
With the impending release of C# 6.0 and all its new features, I have been thinking about what might come in the next version of C# (v7.0, I’m guessing). There has been talk in the Roslyn forums about things such as pattern matching and record types (the latter being especially important since the primary constructors feature was dropped from C# 6.0).
Below is a quick sketch of how I think record classes should work in C#. You can probably tell that I spend a lot of time programming functionally, because I’ve included a number of syntax features here to make immutability a very easy option.
Note: I’m not sure that the “class” keyword is even needed any more. Contrast: “public record class Person” vs “public record Person”
public record class Person
{
string Name { get; set; }
DateTime DoB { get; }
bool IsRobot { get; set; } = false;
}
// Note the lack of visibility modifiers. Like an interface, everything is public in a record class
var john = new Person
{
Name = "John" // Compiler error: A value for "DoB" has not been supplied
}
// This is legal. IsRobot is "optional" because it has a default value in the class definition
var joe = new Person
{
Name = "Joe",
DoB = DateTime.Yesterday
}
joe.Name = "Suzy" // Legal: Name is "mutable" because it has a public setter in the class definition.
joe.DoB = DateTime.Now // Compiler error: "DoB" has no public setter. DoB is "immutable"
public record class Point
{
double X { get; }
double Y { get; }
}
var origin = new Point { X = 0.0, Y = 0.0 }
var location = new Point { X = 0.0, Y = 0.0 }
origin == location // => true. Records have auto-generated structural equality and GetHashcode methods
origin.ToString() // => "Point { X = 0.0, Y = 0.0 }". Records have an auto-generated ToString() method (can be overridden).
// Custom members can be defined, both properties and methods. Note that only auto-implemented properties are required
// when instantiating the record.
public record class Point3D
{
double X { get; }
double Y { get; }
double Z { get; }
override String ToString()
{
return $"({X}, {Y}, {Z})";
}
double Dist => Sqrt(X * X + Y * Y + Z * Z);
}