Understanding C# Structs: A Beginner's Guide with Code Examples

C# is a powerful programming language that offers developers a wide range of features to work with. One such feature is the ability to define and use structs. In this tutorial, we will explore C# structs, including what they are, how they differ from classes, and how to use them in your programs. 

What are C# Structs? 
In C#, structs are a type of value type. They are used to define lightweight objects that can contain a small number of data members. Structs are similar to classes, but there are some important differences between them. 

One of the key differences is that structs are value types, whereas classes are reference types. This means that when you create an instance of a struct, the data is stored on the stack, whereas when you create an instance of a class, the data is stored on the heap. 

Another important difference between structs and classes is that structs cannot be inherited from, whereas classes can. Additionally, structs cannot have default constructors, and all of their data members must be initialized in the struct's constructor. 

Declaring Structs in C# 
To declare a struct in C#, you use the struct keyword followed by the name of the struct. 

Here is an example of a simple struct definition:
struct Point
{
    public int X;
    public int Y;
}
This defines a struct called Point that has two data members, X and Y, both of type int. 

Using Structs in C# 
Once you have defined a struct in C#, you can create instances of it just like you would with a class. 

Here is an example:
Point p = new Point();
p.X = 10;
p.Y = 20;
This creates a new instance of the Point struct and sets the values of its X and Y data members. 

Structs can also be passed as parameters to methods, just like classes. However, because structs are value types, they are passed by value, whereas classes are passed by reference. This means that when you pass a struct as a parameter, a copy of the struct is created and passed to the method, whereas when you pass a class as a parameter, a reference to the class is passed. 

Here is an example of a method that takes a struct as a parameter:
public void DrawPoint(Point p)
{
    // draw the point at (p.X, p.Y)
}
And here is an example of how you would call this method:
Point p = new Point();
p.X = 10;
p.Y = 20;

DrawPoint(p);
This creates a new instance of the Point struct, sets its X and Y data members, and then passes it to the DrawPoint method. 

Using Structs vs. Classes 
When deciding whether to use a struct or a class in C#, there are a few factors to consider. 

One factor is performance. Because structs are value types, they are stored on the stack, which can make them faster to access than classes, which are stored on the heap. However, because structs are copied by value, they can also consume more memory than classes. 

Another factor is semantics. Structs are best used for small, simple objects that are not intended to be modified after creation. Classes, on the other hand, are better suited for larger, more complex objects that may need to be modified or extended over time. 

Finally, you should consider whether you need to use inheritance. Because structs cannot be inherited from, if you need to define an object hierarchy, you will need to use classes. 

A Complete example Program with Structs
using System;

struct Point
{
    public int x;
    public int y;
    
    public void DrawPoint()
    {
        Console.WriteLine($"Drawing point at ({x}, {y})");
    }
}

class Program
{
    static void Main(string[] args)
    {
        Point p1 = new Point();
        p1.x = 10;
        p1.y = 20;
        
        Point p2 = new Point();
        p2.x = 30;
        p2.y = 40;
        
        p1.DrawPoint();
        p2.DrawPoint();
    }
}
The output of the program
Drawing point at (10, 20)
Drawing point at (30, 40)
The program defines a struct called `Point` that has two integer fields representing the x and y coordinates of a point. It then creates two instances of this struct and uses a method called `DrawPoint` to output the coordinates of each point.