Introduction
Understanding the differences between classes, records, and structs is crucial when writing efficient and maintainable code in C#. Each of these constructs serves a distinct purpose and comes with its own set of advantages and trade-offs. In this article, we will explore each of them in detail, along with examples to illustrate their usage.
Classes in C#
Classes are the fundamental building blocks of object-oriented programming in C#. They encapsulate data and behavior into a single unit, providing a blueprint for creating objects. Here's an example of a class:
public class Person
{
public string Name { get; set; }
public int Age { get; set; }
public Person(string name, int age)
{
Name = name;
Age = age;
}
public void DisplayInfo()
{
Console.WriteLine($"Name: {Name}, Age: {Age}");
}
}
In this example, we have a Person class with properties for Name and Age, along with a constructor to initialize these properties and a method DisplayInfo() to display the information.
Records in C#
Records were introduced in C# 9.0 as a concise way to create immutable data types. They are similar to classes but come with built-in value equality semantics. Records are primarily used for modeling data rather than behavior. Here's an example:
public record Person(string Name, int Age);
In this example, we define a Person record with properties for Name and Age. Unlike classes, records implicitly implement value equality, meaning two instances with the same property values are considered equal.
Structs in C#
Structs are value types that are typically used for lightweight objects. They are commonly employed when memory allocation and performance are critical factors, as they are stored on the stack rather than the heap. Here's an example:
public struct Point
{
public int X { get; }
public int Y { get; }
public Point(int x, int y)
{
X = x;
Y = y;
}
}
In this example, we have a Point struct representing a 2D point with X and Y coordinates.
Comparison Between Class, record, and Struct
- Classes: Used for encapsulating both data and behavior. They are reference types and support inheritance, polymorphism, and abstraction. Suitable for complex objects with behavior.
- Records: Primarily used for immutable data modelling. They provide value equality semantics out of the box, making them suitable for data transfer objects, DTOs, and lightweight data containers.
- Structs: Ideal for small, lightweight objects that are frequently created and destroyed. They are value types, meaning they are stored directly where they are declared, leading to better performance in certain scenarios.
Example Usage
class Program
{
static void Main(string[] args)
{
// Using class
var person = new Person("Alice", 30);
person.DisplayInfo();
// Using record
var personRecord = new Person("Bob", 25);
Console.WriteLine($"Name: {personRecord.Name}, Age: {personRecord.Age}");
// Using struct
var point = new Point(10, 20);
Console.WriteLine($"X: {point.X}, Y: {point.Y}");
}
}
Conclusion
Understanding when to use classes, records, and structs is essential for writing clean, efficient, and maintainable code in C#. Classes are versatile and suitable for most scenarios involving behavior encapsulation. Records excel at modeling immutable data with value equality semantics. Structs are beneficial for lightweight objects where performance and memory usage are critical considerations. By leveraging these constructs appropriately, you can design robust and performant applications in C#.