Class vs. Record vs. Struct in C#

Jiyan Epözdemir
.Net Programming
Published in
4 min readDec 22, 2023

In this post, we are going into an overall comparison of C# Class, Struct, and Record. Classes, structs, and, more recently, records are the various ways that C#, allows you to define data structures. Understanding the similarities and differences among these types can assist developers in making well-informed decisions when designing their applications, as each has unique features and use cases of its own.

Classes

Classes are the most commonly used type of data structure in C#. They are reference types, which means that when an object is created from a class, a reference to that object is created, and the reference is passed around rather than the object itself.

Classes can contain data members, which are variables that store data, and methods, which are functions that operate on that data. They are often used to model complex objects with multiple data members and methods. For example, consider a class that represents a person with properties for their name, age:

public class Person
{
public string Name { get; }
public int Age { get; set; }

public Person (string name, int age)
{
Name = name;
Age = age;
}

public void Greetings()
{
Console.WriteLine($"Hi, my name is {Name}.");
}
}

// Usage
var p1 = new Person("Jepozdemir", 36);
var p2 = p1;
p2.Age= 40;
Console.WriteLine(p1.Age); // Output: 40
Console.WriteLine(p2.Age); // Output: 40

Note that, when we modified the “Age” property of the instance p2, the same property of the p1 instance is also changed. This is because, classes are reference types in C#. In other words, the actual data is stored in the same place in memory that is referenced by both objects. Two person objects in this example refer to a single memory item. So, we get the same value for the properties of this two objects.

Structs

Structs are value types, which means that when an object is created from a struct, a copy of that object is created and passed around rather than a reference to it.

Structs can also contain data members and methods, just like classes.

Structs are often used to represent small, lightweight objects that don’t require the overhead of a reference type. For example consider a struct that represents a square:

public struct Square
{
public int Side { get; set;}

public Square (int side)
{
Side = side;
}

public int Perimeter()
{
return 4 * Side;
}
}

// Usage
var s1 = new Square(10);
var s2 = s1;
s2.Side= 5;
Console.WriteLine(s1.Perimeter()); // Output: 40
Console.WriteLine(s2.Perimeter()); // Output: 20

Note that, the struct object s2 was created from the object s1. Opposite of classses, the changes on object s2 did not affect the object s1. This is because structs are value types. They refer own different locations in the memory for each instance or objects.

As far as structures versus classes, structures are more limited, so you may need classes when you need inheritance and reference comparisons.

Records

Records were introduced in C# 9 as a new type of data structure that combines the best of both classes and structs. Records are reference types, like classes, but they have a simpler syntax and provide built-in functionality for comparing and hashing objects, like structs.

Records are usually used to represent immutable data structures, such as a point in time, a currency amount, or a configuration object.

Records are able to inherit from one another, like classes. For example, consider a base record that represents a vehicle and another record derived from vehicle represents a car:

It is important to note that, both classes and records are incapable of inheriting from one another.

public abstract record Vehicle
{
public string Brand { get; set; }
}

public record Car: Vehicle
{
public int MaxSpeed { get; set; }
}

var mercedes = new Car { Brand = "Mercedes", MaxSpeed = 240};

// likewise, you can use the expression (only C# 10 or higher)
public abstract record Vehicle(string brand);
public record Car(string brand, int maxSpeed) : Vehicle(brand);

var mercedes = new Car ("Mercedes", 240);

Records can also contain methods, just like classes and structs:

public record Car
{
public int Speed { get; set; }

public void SpeedUp()
{
Speed +=10;
}
}

A record’sToString method creates a formatted string that represents an object's type name and the names and values of all its public properties.

var mercedes = new Car ("Mercedes", 240);
Console.WriteLine(mercedes.ToString());

// Output:
// Car { Brand = Mercedes, Speed = 240 }

Records are good for when your data should not change. Records can be inherited from other records, so it’s good to have that when you don’t really need to have a whole class for what you need.

Records are also convenient when you want your comparisons on the instances to be based on value.

public record Car(string brand, int maxSpeed) ;

var car1 = new Car ("Mercedes", 240);
var car2 = new Car ("Mercedes", 240);

// Output: True, because records provides value-based equality
Console.WriteLine(car1 == car2);

To briefly mention the key characteristics of these three data structures; Classes are reference types and more flexible, structs are value types and are more lightweight, while records provides the immutability and value-based equality semantics.

Conclusion

In conclusion, these are just fundamental overviews of primary data structures. Classes, structs, and records are all useful data structures in C# with their own unique features and use cases. Understanding the differences between them can help you make informed decisions when designing your applications.

Sample codes used here are available in the following GitHub repository:

Thank you for reading, I hope it was helpful!

If you found this post helpful, don’t forget to give it a clap and share it with others who might benefit from it.👏👏👏👏👏

--

--

Jiyan Epözdemir
.Net Programming

I am a multi-disciplined Software Architect and Computer Engineer, MSc. I enjoy building awesome softwares & applications.