{ }codelper

Learn › C#

Language-specific · 36

Structs

Bundle related values into one unit, and know whether that unit is copied or shared.

This lesson is for C# · C++ · C.
Python, JavaScript, TypeScript and Java group data with classes and objects (see the classes lesson), and Craykon uses 사전() dictionaries.
In all of them assignment shares the same object through a reference, unlike a struct, which is copied.

Values that always travel together, like a point's x and y or a student's name and score, are grouped into a struct.
The example below copies a point, changes only the copy, then moves the original, to show how copy and original differ.

using System; struct Point  // 값 타입: class로 바꾸면 q = p 가 같은 객체를 가리켜요{    public int X, Y;    public void Move(int dx, int dy) { X += dx; Y += dy; }    public int Len2() => X * X + Y * Y;    public override string ToString() => $"({X}, {Y})";} class Program{    static void Main()    {        string[] t = Console.ReadLine().Split();        var p = new Point { X = int.Parse(t[0]), Y = int.Parse(t[1]) };        Console.WriteLine($"p = {p}");         Point q = p;  // 데이터가 복사돼요        q.X = 10;        Console.WriteLine($"q = {q}");        Console.WriteLine($"p = {p}");         p.Move(1, 1);        Console.WriteLine($"p = {p}");        Console.WriteLine($"len2 = {p.Len2()}");    }}
stdin
3 4
stdout
p = (3, 4)
q = (10, 4)
p = (3, 4)
p = (4, 5)
len2 = 41

Key points

  • One bundle becomes a new type.
    You can pass it, return it and store it in an array as a single variable.
  • The values inside are members (fields), read with a dot like p.x.
  • Assigning a struct or passing it to a function copies every member.
    So after q = p and q.x = 10, p is still (3, 4).
  • To change the original, pass a pointer or a reference.
    Big structs are expensive to copy, so they are often passed by const pointer or reference even when only read.

How each language writes it

C#A struct is a value type, so Point q = p; copies the data; a class is a reference type, so the same assignment points at the same object (make the example class Point and after q.X = 10, p is (10, 4) too) — int, double and DateTime are structs.
Use struct for small values like coordinates, colours and dates (readonly struct or record struct to make them immutable), and class otherwise.
Pass the original with ref
C++Just Point, no typedef.
A struct can hold member functions (void move(int dx, int dy)), and ones that don't modify get const, like int len2() const — struct and class differ only in default access (public for struct, private for class).
Pass the original as Point& or const Point&
Cstruct Point { int x, y; }; needs struct Point p; every time, so people usually write typedef struct { int x, y; } Point; — change the original with move(&p, 1, 1), reach members through a pointer with p->x instead of (*p).x, and use const Point * when only reading

Common mistakes

Changing a member of a struct in a listC#

var list = new List<Point> { new Point() };
list[0].X = 5;

→ Compile error CS1612: the indexer returns a copy. arr[0].X = 5 on an array works, but a struct taken out by foreach can't be changed either (CS1654)

Take the copy out, change it, and put it back: var t = list[0]; t.X = 5; list[0] = t;

Comparing structs with ==

if (p == q) { … }

→ A compile error in C. In C++ without an operator==, and for a C# struct that doesn't define == (CS0019), it is a compile error too

In C, compare member by member (memcmp can be wrong because of padding bytes between members).
C++20 can write bool operator==(const Point&) const = default;; in C#, p.Equals(q) compares member values, and record struct generates == as well.

Taking it by value moved only the copyC · C++

void move(Point p, int dx, int dy) {
    p.x += dx;
    p.y += dy;
}

→ The caller's p doesn't change. No error, no warning

Take a Point * in C, or a Point& in C++.

How languages differ
Every time you pass or assign a struct, ask whether it is a copy or the same thing.
C, C++ and C# structs are copied, so changing the original takes a pointer (Point *), a reference (Point&) or C# ref, while a C# class shares one object.

Practice