Understanding Class vs Struct vs Record in C# with examples

The main difference between class, struct, and record is that classes are reference types, structs are value types, and records are immutable reference types.

class-vs-struct-vs-record-in-csharp
Class vs Struct vs Record in C#
  • Classes are reference types that store data on the heap. They are well-suited for creating complex objects that may require features like inheritance, polymorphism, and encapsulation.
  • Structs are value types that store data directly on the stack. They are suitable for efficiently storing small and simple data types, making them a good choice when performance is a priority.
  • Records, like classes, are reference types that store data on the heap. However, records are specifically designed to represent immutable data structures. Immutable means that it cannot be changed once the data is set. Records provide built-in functionality for comparing and hashing objects, making them useful for scenarios where data integrity is important.

Tabular comparison: Class vs Struct vs Record in C#

Here is a tabular comparison between Class, Struct, and Record in C#:

Memory AllocationPerformanceMutabilityInheritanceEncapsulationDefault Constructors
Class:Class is stored on the heap.Slightly slowerMutableSupportedClass can have private fields.Generated (if not defined)
Struct:Struct is stored on the stack.Faster accessImmutable/MutableNot supportedStruct fields are always public.Not generated
Record:Record is stored on the heap.Slightly slowerImmutableSupportedRecord can have private fields.Generated (if not defined)
class vs struct vs record

When should I use a class, a struct, or a record?

In C#, you should choose between a class, a struct, or a record based on your specific needs and requirements:

Class:

  • Choose a class when you need a reference type that can contain methods, properties, and fields.
  • Use classes for more complex data structures that require inheritance, polymorphism, or complex behavior.
  • Classes are suitable for creating objects that may have a longer lifetime and need to be reused or shared among multiple parts of your program.

Struct:

  • Use struct when you need a value type that is lightweight and efficient in terms of memory usage.
  • Opt for a struct when you require a fast data structure. Structs are value types typically used for small, simple pieces of data, such as numeric types (int, float) or custom structures.
  • Use structs for small, simple data structures that don’t require inheritance or complex behavior.
  • Structs are an excellent choice when you want to ensure value-type semantics and avoid the overhead of heap allocation as they are directly stored in the stack memory.

Record (C# 9.0 and later):

  • Consider a record when you need an immutable data structure with value semantics.
  • Records are designed to represent data that doesn’t change after creation, and they come with built-in value-based equality checks.
  • Use records for simple data transfer objects (DTOs), data storage, or any scenario where immutability and equality are crucial.

In sort, If you need a data structure that is immutable and efficient, then a record is a good choice. If you need a data structure that can be inherited from other classes or that contains methods, properties, fields etc. then a class is a good choice. If you need a data structure that is lightweight and fast, then a struct is a good choice.

Read more about Value Type and Reference Type in C#.

C# Class

A class is a fundamental concept in object-oriented programming. It is a user-defined data type that serves as a blueprint for creating objects and defining their properties (attributes) and behaviors (methods).

In C#, classes are reference types, which means they store data on the heap. They are great for creating complex objects that can inherit properties and behaviors from other classes, and they also support features like polymorphism and encapsulation.

As Classes are reference type, Its means that if you change the value of a field in one instance of a class, the value of that field will also change in any other instances of the class that refer to the same object.

We use classes to encapsulate related data and functionality, which makes it easier to reuse and maintain code.

Let’s consider an example of Class in C#:

using System;

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

    public void SayHello()
    {
        Console.WriteLine("Hello, I am " + Name);
    }
}

In the above code snippet, we define a class called Person with two properties: Name and Age. We also have a method called “SayHello()” to greet the person.

We can create objects of this class by using the new keyword, which allows us to access the properties and invoke methods.

class Program
{
    static void Main(string[] args)
    {
        Person person = new Person();
        person.Name = "Shekh Ali";
        person.Age = 29;

        person.SayHello();
        Console.ReadLine();
    }
}

Output:

Hello, I am Shekh Ali

Read more about Class and Objects in C#.

C# Struct

A struct, or structure, is a value type in C#. Unlike classes, structs are lightweight and store data directly on the stack. They are primarily used for storing small amounts of data, making them a good choice when performance is a priority.

As struct is a value type, meaning that when you create an instance of a struct, you are creating a copy of the struct’s data.

It means that if you change the value of a field in one instance of a struct, the value of that field will not change in any other instances of the struct.

Let’s consider an example of struct in C#:

using System;

public struct Point
{
    public int X { get; set; }
    public int Y { get; set; }

    public void Display()
    {
        Console.WriteLine("X: " + X + ", Y: " + Y);
    }
}

public class Program
{
    public static void Main()
    {
        Point point = new Point();
        point.X = 10;
        point.Y = 5;

        point.Display();
    }
}

Output:

X: 10, Y: 5

Read more about Struct in C#.

C# Record

A record is a reference type that is immutable by default. It means that once you create an instance of a record, you cannot change the value of any of its fields. Records are a good choice for data structures that need to be consistent and reliable.

Record was introduced in C# 9.0. They are special objects that bring together the characteristics of structs and classes. Like classes, records are reference types and store data on the heap.

One of the benefits of records is that they provide built-in features for comparing and hashing objects, which helps to maintain data integrity. Records are particularly useful in situations where you need to ensure that your data remains consistent and unaltered.

Here are two examples to demonstrate the usage of “record” in C#. In one example, we will use it like a struct and the other like a class:

Example 1: Using “record” like a struct

public record Point(int X, int Y);

// Usage
Point point1 = new Point(5, 10);
Point point2 = point1 with { X = 8 };
Console.WriteLine($"Point 1: X={point1.X}, Y={point1.Y}");
Console.WriteLine($"Point 2: X={point2.X}, Y={point2.Y}");

Output:

Point 1: X=5, Y=10
Point 2: X=8, Y=10

In this example, the record keyword is used to defines a data structure called “Point,” which acts similarly to a struct. It has two properties, X and Y, representing coordinates.

When we want to make changes to a property, we use the with keyword to create a new instance of the record with the updated value. It shows that the record is immutable, meaning it cannot be changed directly; instead, a new instance is created with the modified property.

Example 2: Using “record” like a class

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

// Usage
Person person1 = new Person { FirstName = "Shekh", LastName = "Ali" };
Person person2 = new Person { FirstName = "Roman", LastName = "Chug" };
Console.WriteLine($"Person 1: {person1.FirstName} {person1.LastName}");
Console.WriteLine($"Person 2: {person2.FirstName} {person2.LastName}");

Output:

Person 1: Shekh Ali
Person 2: Roman Chug

In the above code example, we use the “record” keyword to create a structure similar to a class called “Person.” It has properties for the person’s first name and last name.

It is important to mention that we use the init keyword for these properties, which means they can only be set when the object is first created.

This highlights the fact that records are immutable, meaning their values cannot be changed once they are set. We can create objects of this record type and access their properties in the same way we do with classes.

Key points about classes, structs, and records in C#:

  • Storage: Classes and records are reference types, while structs are value types. It means that when you create an object of a class or record, the object is stored on the heap, while when you create an object of a struct, it is stored on the stack.
  • Encapsulation: Classes and records can have private members, which are only accessible to the class or record itself. Struct members are always public, which means that they can be accessed by any code that has a reference to the struct.
  • Equality: Classes and records can be compared for equality using the == operator. The equality of two structs is determined by the values of their members. The equality of two records is also determined by the values of their members, but records also have built-in support for value equality.
  • Inheritance: Classes can inherit from other classes, and records can inherit from classes. Struct cannot inherit from other types except interface.

Here are some examples of when to use each type:

  • Use a class when you need to create a complex object with multiple properties and methods. For example, you might use a class to represent a customer, an order, or a product.
  • Use a struct when creating a simple object with a few properties. For example, you might use a struct to represent a point, a color, or a size.
  • Use a record when you need to create an immutable lightweight object with built-in support for equality and hashing. For example, you might use a record to represent a person’s name, age, and address.

FAQs

Q: What is the main difference between a class, struct, and record in C#?

The Classes are reference types, structs are value types, and records are reference types with built-in object comparison and hashing.
In short, classes are used for complex objects, structs for lightweight storage, and records for immutable data structures.

Q: Can I use records in older versions of C#?

Records were introduced in C# 9.0. To use records, you’ll need to have a compatible version of C# or later version.

Q: Are there any performance differences between classes, structs, and records?

Yes, there can be performance differences. Structs, being value types stored on the stack, provide faster access and are generally more memory-efficient. Classes and records are reference types stored on the heap and have a slight performance overhead due to heap allocation and garbage collection.

Q: Are default constructors generated for classes, structs, and records?

Classes and records have default constructors generated automatically if not explicitly defined. However, structs do not have default constructors generated by the compiler.

Q: Why use record instead of class in C#?

Records are often preferred over classes in C# when you need to represent immutable data structures or when you want to simplify code with built-in behaviors for object comparison and hashing.

Q: What is the difference between a class and a struct?

A class is a reference type, while a struct is a value type. It means that when you create an instance of a class, you are creating a reference to that instance. When you create an instance of a struct, you are creating a copy of the struct’s data.

Conclusion

In conclusion, understanding the differences between C# Class, Struct, and Record is important for making informed decisions in code design. 

Classes are suitable for creating complex objects with features like inheritance and polymorphism. Structs work well for lightweight data storage, especially with small and simple data types. Records shine in scenarios where immutable data structures and built-in object comparison are desired.

Recommended Articles:

Shekh Ali
4.5 2 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Inline Feedbacks
View all comments