C# Struct: Everything you need to know [2023]

By Josip MiskovicUpdated on
A thumbnail showing code. Everything you need to know about C# struct data structure.

Have you ever used a struct in C#?

You might be surprised, but int, bool and DateTime are all structs.

Structs are a great feature of C# that lets us structure our data.

Let's learn more about them.

What is a struct?

A C# struct is a value type with the main purpose of storing data in a structured way. Classes are more about defining behavior, while structs give us a way to structure data.

Structs are stored on the stack and they cannot be null. Unlike classes, structs do not support inheritance. Also, you do not need to use the new keyword to create a struct.

So, structs:

  • Are value types
  • Do not support inheritance
  • Can implement interfaces
  • Are stack-allocated
  • Cannot be null

How to use a struct?

Definition

To define a struct in C#, we use the struct keyword:

C#
public struct Color
{
	 public string Name;
}

We can break the above code to:

  • public - access modifier
  • struct - keyword to define it's a structure
  • Color - the struct name
  • public string Name - structure member

Initialization

To initialize a struct, we use the new operator:

C#
var blue = new Color() { Name = "Blue" };

We can also define structs without the new keyword, like this:

C#
Color c;
c.Name = "Blue";

If you use this method to initialize a struct, the fields will remain unassigned.

Access

To access struct members, we use the dot . syntax:

C#
Console.WriteLine(blue.Name);

Default values

If we don't change the values, the default value for struct members is the same as the default value for each field inside the struct.

If we have a struct defined as:

C#
public struct Color
{
	 public string Name;
}
var blue = new Color();

The default value of the field Name will be default(string) which is null.

When to use a struct?

Structs store data. Classes define behavior.

Structs are ideal for simple structures or data carriers.

These questions will help you decide whether to use a struct:

  1. What is the primary responsibility of this type? Is it data storage?
  2. Is its public interface defined entirely by properties that access or modify its data members?
  3. Will this type ever have subclasses?
  4. Will this type need polymorphism?

What are the disadvantages of structs?

The main disadvantages of structs are:

  • Structs do not support inheritance: Inheritance is a common object-oriented technique that allows for extending functionality.
  • Expensive to copy, which impacts performance: If we pass the struct between methods, data gets copied. It might not seem much, but we can easily get in trouble if we have a large list of structs.

Struct Use Cases

The most common use for structures is for simple grouping of data. The best example of it is the native implementation of .NET libraries.

Let's look at the .NET Framework reference source.

For example, the C# nullable wrapper uses a struct:

C# Nullable struct
Source code for the Nullable struct.

Another great example is the DateTime struct. It has a lot of data manipulation and it’s interesting to see how they’ve used struct members to organize date representation.

DateTime struct source code

What's the difference between a struct and a class?

The main difference between struct and class in C# is that structs are value types, while classes are reference types. Classes support inheritance, but structs don't. Classes can have a null reference, while structs can't.

This table summarizes the differences between structs and classes:

ClassStruct
Reference typeValue type
Support inheritanceNo inheritance
Can have null referenceCannot have null reference
Contain complex logicLight on logic, they structure data
Can have parameterless constructorsCan have parameterless constructors

What's the difference between a struct and a record?

The main difference between struct and record is that struct is a value type, while a record is an immutable object.

Structs are better for structures that are similar to primitive data types such as int, bool, and double. On the other hand, records are better for encapsulating complex data.

What's the difference between reference type and value type?

The main difference between reference types and value types is that value types are meant to be small and lightweight, while reference types form more complex class hierarchies.

When we pass a value type to a method, the instance of that value type is copied. On the other hand, reference types pass a memory reference, so they are not copied.

Example: Reference Type vs Value Type

In C#, an integer (int) is an example of a value type, while a string is a reference type.

When we pass an integer to a method, a copy of that integer value is passed. And any changes made to that integer within the method do not affect the original integer outside the method.

C#
int x = 10;
ChangeInteger(x);
Console.WriteLine(x); // Output: 10. The original variable is not changed!

void ChangeInteger(int y)
{
  y = 20;
}

On the other hand, when we pass a string as a parameter to a method, a reference to the memory location of that string is passed to the method. Any changes made to that string within the method affect the original string.

C#
string s = "hello";
ChangeString(s);
Console.WriteLine(s); // Output: world. The original variable is changed!

void ChangeString(string t)
{
t = "world";
}

Read-only structs

A read-only struct ensures that all fields are read-only. This makes it easier to declare intent, and also allows the compiler more optimization freedom.

Read-only structs are a great way to prevent defensive copying. They give developers more confidence that data won’t change.

Which modifiers does struct support?

Structs support the same modifiers as classes. These are:

  • new
  • public
  • protected
  • internal
  • private
  • unsafe_modifier

Structs in C# should be designed to be immutable, which means they cannot change their internal state after they have been created.

Can structs implement interfaces?

Structs can implement interfaces. The C# community rarely recommends it because it makes boxing more likely.

From my experience, I think of structs as a very specific group of data. So having different implementations isn't very useful.

What is boxing in C#?

In C#, boxing is converting a value type to an interface that this value type implements.

Converting a struct to an interface causes boxing.

When we box a value, it creates a new object on the heap and copies the value into it. The new allocation might lead to performance degradation.

C# Boxing of a struct

Example of boxing in the Intermediate Language (IL) when we box a struct.

Default parameterless constructor

Starting C# 10.0, structs can have parameterless constructors.

That means we can define our defaults in one place. For example:

C#
public struct Color
{
	public string Name;
	public Color()
	{
		Name = "N/A";
	}
}

Parameterless constructors are a much cleaner way to write code because all our values are in one place.

Before C# 10.0, parameterless constructors didn't work. We would get a compile-time error:

error CS0568: Structs cannot contain explicit parameterless constructors

Struct performance

Adam Sitnik from Microsoft ran a series of tests to compare the performance of value types and reference types.

When you pass a value type to or from a method, the copy is made every time. The more fields the struct has, the more expensive copying becomes.

Use ref's to improve performance

To improve the performance of structs we can pass them by reference using the ref keyword. That way, when we pass a struct to a method, we pass a reference rather than a copy.

C# Structs: Summary

  • A C# struct is a value type with the main purpose of storing data in a structured way.
  • The struct object passed around is copied, changing any properties of the original object does not affect the copies.
  • Structs are useful for representing small pieces of data.
  • When designing your types, be sure to consider if their functionality fits better in a struct or class structure.
  • Unlike classes, structs cannot be inherited.
  • Having a default parameterless constructor for structs in C# 10.0 makes it much easier to define types without repeating code.
  • ref modifier is used for passing references to value types to improve performance.
Josip Miskovic
About Josip

Josip Miskovic is a software developer at Americaneagle.com. Josip has 10+ years in experience in developing web applications, mobile apps, and games.

Read more posts →

Last modified on:
Download Free Software Developer Career Guide

I've used these principles to increase my earnings by 63% in two years. So can you.

Dive into my 7 actionable steps to elevate your career.