I’m a long-time C# developer, but I currently do not work with it so I’m a little out of the loop. I have seen the new records feature in C# 9, and I can’t understand how that feature survived the “every feature starts with -100 points” test.

As my understanding, it allows you to write

record Person(string FirstName, string LastName)

instead of

class Person {
public string FirstName { get; init; }
public string LastName { get; init; }
}

with the only differences being that

  1. You need to use a parameterized constructor instead of object initialization. I guess it’s a matter of taste, but I’m not sure this is even better.

  2. You get some equality methods automatically implemented. I avoid using equality anyway (because what does it mean that two persons are “equal”? same name? or must they be the exact same person?)

  3. You get an automatic ToString, which I guess could be nice for debugging or logging

  4. You get a Destruct method, which I guess could make sense for some really special types like `Point` but I don’t feel this should be overused.

Am I missing some killer feature of records, or are they intended as a first step towards some more powerful feature?

I’ve been only using them very little, but I think the draws are that they show intention. A record is always immutable, while a class can be made immutable. I also believe a record has some auto-generated functions relating to comparison and easy copy methods, that allow a short-hand when you want a copy of a record with one field changed.

Under the covers records are simply classes. So these are just convenience things. A record cannot do anything a class cannot do, but it will make you type less code for some of those things.

I did point out the comparison methods and how unnecessary they are in my OP. The “with one field changed” part might be interesting though, how does that work?

What’s the point of records other than all of these points? Well, none.
The point of records is generating lots of common boilerplate code for you. Properties, constructors, value equality, and copy constructors for with expressions, implemented in a way that supports inheritance. If you want to write that boilerplate yourself or you don’t need those features, you don’t need records. Just like you don’t technically need auto properties, async await, yield return, etc.

Records can be immutable
The OP’s example with class is also immutable. I think that’s point of his question, really.

Point 2 is a pretty big deal to me, and point 3 is nice too.
because what does it mean that two persons are “equal”? same name? or must they be the exact same person?

Short answer: it means, are they the same record from the person table in the database? i.e. if they have the same unique id, then they are equal (and will also have all other fields equal).

Other answer: same individual person. It can’t merely be same name, as there are many duplicates in real life: John Smith, age 35, from Peoria is != John Smith age 27 from Dayton. That’s why there are SSNs and other unique ids.

It seems that you never used F#, OCaml, Haskell, Typescript or another language with decent support to Algebraic Data Types.

Records are the first small step in the right direction, they are a decent implementation of an immutable product type.

Now we need Discriminated Unions to have the sum type.
Honestly I was extremely pleased when I saw the final record implementation. I was following it from the early beginning and it was a huge, ungodly, bloody mess that wasn’t compact at all.

Records in C# 9 are an extremely useful and compact way to define an immutable class with a sensible implementation of the equality and formatting members.

source