Record vs Class vs Struct and more, C# 9

Gal Ilinetsky
CodeX
Published in
3 min readOct 24, 2022

Value types and reference types are the two main categories of C# types. A class is one of the keywords to declare a reference type in C#. Struct is a value type that can encapsulate data and related functionality.

I will not start explaining in depth the differences between value types and reference types but one of the differences is regarding value equality.

Value equality

Value equality means that two objects contain the same value or values.

Class

When it comes to Class we can use the method Object.Equals that determines whether two object instances are equal. The default implementation of Equals supports reference equality for reference types. Reference equality means the object references that are compared refer to the same object, meaning they point to the same address on the heap.

Struct

When it comes to a Struct we can use the ValueType.Equals(object? obj) method that returns true if obj and this instance is the same type and represents the same value. This implementation uses reflection to examine all the fields and properties.

In the following example, we have a CProduct class and a SProduct struct both have the same properties.

When we create two identical(by properties value) instances of both, we can see that Equals returns true for the struct instance and false for the class instance, just as we explained.

Two more things you should notice are :

  1. The hashCode value for two identical(by properties value) instances is the same for struct and different for class.
  2. operator: == and != operators can’t operate on a struct unless the struct explicitly overloads them.

Record

C# 9.0 introduces record types

In C# 9 we are introduced to a new type: record. It is a reference type that offers a few features such as immutability.

This is how we can declare a record:

public record RProduct(int Price, string name);

When it comes to value equality, records behave like value types:

You can see that not only the method Equals behaves the same as for struct , but we also have the option to use == and != operators.

In addition, the hashCode value for two identical(by properties value) instances is the same.

Built-in formatting for display

Contrary to the default implementation for ToString() in classes and structs , which just returns the following :

namespae.object-type

record types have a compiler-generated ToString() that displays the names and values of public properties and fields. ToString() returns a string of the following format:

<record type name> { <property name> = <value>, <property name> = <value>, …}

Deconstruct Method

When creating a record the compiler creates a Deconstruct method with an out parameter for each positional parameter provided in the record declaration.

This is what the method will look like:

As you can see record is a very nice feature, may not always be the right choice to use, but it is definitely a refreshment to C#. It enables us to have a “value-type” object that is actually a reference type that is also thread-safe as part of its immutability.

--

--

Gal Ilinetsky
CodeX
Writer for

Software Engineer, .net development focus. Here to share my knowledge on points of view on software development fields I take interest in.