Struct in C#

Struct in C# is a value type used to group related data and behavior into one lightweight type. It is useful when you want an object-like design but the data represents a small, self-contained value such as a point, color, rectangle, date range, or measurement.

At first glance, a struct looks similar to a class because it can contain fields, properties, methods, constructors, and interface implementations. The important difference is that a struct is a value type, while a class is a reference type. That difference affects memory behavior, copying, assignment, method calls, and performance decisions.

Understanding structs is important because many core .NET types are structs, including int, double, bool, DateTime, Guid, and TimeSpan. If you do not understand how value types behave, it becomes easy to make subtle mistakes in real applications.


What Is Struct in C#?

A struct is a user-defined value type declared with the struct keyword. It groups related members together, just like a class, but instances are copied by value unless boxing or references are involved.

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

The Point struct stores two related integer values. Because it is a value type, assigning one Point variable to another copies the data rather than sharing one object reference.

Syntax of Struct in C#

accessModifier struct StructName
{
    // fields
    // properties
    // constructors
    // methods
}

Structs support many of the same members as classes, but their usage rules are different because of value-type semantics.

Creating and Using a Struct in C#

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

Point p1 = new Point();
p1.X = 10;
p1.Y = 20;

Console.WriteLine($"({p1.X}, {p1.Y})");

Here, p1 contains its own copy of the data. If you assign p1 to another variable, the values are copied.

Point p2 = p1;
p2.X = 99;

Console.WriteLine(p1.X); // 10
Console.WriteLine(p2.X); // 99

This is one of the biggest differences between structs and classes. With a class, both variables would usually refer to the same object. With a struct, each variable gets its own copy.

Struct Is a Value Type

Value types are copied on assignment and usually stored directly where they are declared. That is why structs behave differently from reference types. A struct variable contains the actual data, not just a reference to separately allocated object data.

This makes structs useful for small immutable data models where copy-by-value is a natural fit. Examples include coordinates, dimensions, percentages, vectors, and compound numeric values.

Struct vs Class in C#

PointStructClass
Type categoryValue typeReference type
AssignmentCopies dataCopies reference
Inheritance from another user classNot supportedSupported
Can be null by defaultNo, unless nullableYes
Typical use caseSmall value-like dataComplex objects and shared state

This table captures the design difference. Use a struct when the value itself matters. Use a class when identity, shared mutable state, or inheritance matters.

Fields and Properties in a Struct

Structs can contain both public fields and properties. In many real projects, properties are preferred because they provide better encapsulation and future flexibility.

public struct Rectangle
{
    public int Width { get; set; }
    public int Height { get; set; }

    public int Area => Width * Height;
}

This struct behaves like a clean value model. It stores width and height, and computes area when needed.

Methods in a Struct

Structs can contain methods just like classes. This helps keep data and the operations related to that data together.

public struct Temperature
{
    public double Celsius { get; set; }

    public double ToFahrenheit()
    {
        return (Celsius * 9 / 5) + 32;
    }
}

If the behavior is tightly related to the stored values, placing the method inside the struct is often a good design choice.

Constructors in a Struct

Structs can have constructors, but they must leave the struct fully initialized before returning. Every field must have a value by the time the constructor ends.

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

    public Point(int x, int y)
    {
        X = x;
        Y = y;
    }
}

This constructor makes initialization clear and safe. It is especially useful when the struct should always begin in a valid state.

Default Value of a Struct

Every struct has a default value in which all fields are set to their own default values. For example, numeric fields become 0, bool becomes false, and reference-type fields inside the struct become null.

Point p = default;
Console.WriteLine(p.X); // 0
Console.WriteLine(p.Y); // 0

This behavior is important because a struct can exist in its default state even if that state is not meaningful for your domain. Good struct design accounts for that possibility.

Readonly Struct in C#

If a struct should not change after creation, you can declare it as a readonly struct. This helps communicate intent and can prevent accidental copying or mutation issues in some cases.

public readonly struct Distance
{
    public double Meters { get; }

    public Distance(double meters)
    {
        Meters = meters;
    }
}

Readonly structs are often a strong choice for mathematical, financial, and measurement values that should behave like immutable data.

Structs Can Implement Interfaces

A struct cannot inherit from a user-defined base class, but it can implement interfaces. This allows structs to participate in abstractions without giving up value-type behavior.

public struct ProductCode : IFormattable
{
    public int Value { get; set; }

    public string ToString(string format, IFormatProvider formatProvider)
    {
        return Value.ToString(format, formatProvider);
    }
}

Implementing interfaces is common for comparability, formatting, enumeration, and custom behaviors in framework-friendly value types.

Boxing and Unboxing with Struct

When a struct is converted to object or to an interface it implements, boxing may occur. Boxing wraps the value type inside an object. Later, unboxing extracts it back into a value type.

int number = 25;
object boxed = number;    // boxing
int unboxed = (int)boxed; // unboxing

Boxing creates overhead. It is not always a problem, but it matters in hot code paths, high-frequency loops, or performance-sensitive systems.

When to Use Struct in C#

  • When the type represents a single value or a small group of closely related values.
  • When instances are small and inexpensive to copy.
  • When immutability is preferred or natural.
  • When the type does not need inheritance from a base class.
  • When value semantics make more sense than shared object identity.

Examples include vectors, coordinates, colors, money amounts, intervals, and strongly typed identifiers.

When Not to Use Struct

  • When the type is large and expensive to copy frequently.
  • When the type depends heavily on identity and shared mutable state.
  • When inheritance from another class is required.
  • When developers may expect reference-like behavior.

If your model behaves more like an entity than a value, a class is usually the safer design.

Common Mistakes with Structs

  • Expecting assignment to share the same data like a class reference.
  • Designing very large mutable structs that are expensive to copy.
  • Forgetting that a struct can exist in its default zero-initialized state.
  • Accidentally causing boxing in performance-sensitive code.
  • Using mutable structs in confusing ways inside collections or properties.

Mutable structs deserve special care. A copied struct may be changed without affecting the original value, which can surprise developers who mentally treat it like a class instance.

Best Practices for Struct in C#

  • Keep structs small and focused.
  • Prefer immutability when possible.
  • Use properties or readonly fields to keep state controlled.
  • Document expected value semantics clearly in APIs.
  • Avoid unnecessary boxing in hot paths.

Struct Interview Points

For interviews, remember that a struct is a value type, a class is a reference type, assignment copies the data, and a struct cannot inherit from another user-defined class. Structs can implement interfaces, can have constructors, and can be nullable through StructName?.

You should also remember boxing and unboxing, the default zero-initialized state, and the practical rule that structs work best when they model small values rather than large object graphs.

FAQs on Struct in C#

What is the difference between struct and class in C#?

A struct is a value type, so assignment copies the data. A class is a reference type, so assignment usually copies the reference to the same object.

Can a struct have methods and properties?

Yes. A struct can contain fields, properties, methods, constructors, and interface implementations.

Can a struct inherit from another class?

No. A struct cannot inherit from a user-defined class, but it can implement interfaces.

When should I use a struct?

Use a struct when the type represents a small value with value semantics, such as a coordinate, measurement, color, or compact data model.

Nullable Struct in C#

A normal struct cannot be null because it is a value type. If you need the idea of an optional value, use StructName? or Nullable<StructName>. This is common when a value may be missing, such as an optional date, coordinate, or measurement.

Point? selectedPoint = null;

if (selectedPoint.HasValue)
{
    Console.WriteLine(selectedPoint.Value.X);
}

This feature is useful because it preserves value-type behavior while still allowing the absence of a value to be represented clearly.

Structs in Real Applications

In real applications, structs work well for coordinates in graphics, money-like values in controlled domains, ranges, angles, and compact configuration values passed between methods. They are especially effective when each instance represents data rather than identity.

For example, a drawing program may use a Point struct for pixel coordinates, while a game engine may use a vector struct for position and direction math. In these cases, value semantics are natural because copying the numbers is often the correct behavior.

That is why struct design is usually strongest when the type is small, meaningful on its own, and easy to reason about as a copied value rather than as a shared object instance.