Classes, objects and constructors
↑Examples are independent C# snippets for modern .NET console projects unless noted otherwise. Class declarations and top-level code can live in Program.cs when top-level statements come first.
At a glance
Section titled “At a glance”A class describes a reference type; an object is an instance of that class. Fields store state and methods express behavior. Constructors establish a valid initial state.
How it works
Section titled “How it works”Members and object creation
Section titled “Members and object creation”new creates an instance. Each instance owns its non-static fields. A constructor has the class name, has no return type and runs when an instance is created.
Player player = new("Alex");player.AddPoints(5);Console.WriteLine($"{player.Name}: {player.Score}");
public class Player{ public string Name { get; } public int Score { get; private set; }
public Player(string name) => Name = name; public void AddPoints(int amount) => Score += amount;}Encapsulation and responsibility
Section titled “Encapsulation and responsibility”Prefer private fields and methods that maintain object invariants. Public properties can expose read-only state without allowing arbitrary writes. A constructor should validate arguments when they are essential for a usable object.
public sealed class BankAccount{ public decimal Balance { get; private set; } public void Deposit(decimal amount) { if (amount <= 0) throw new ArgumentOutOfRangeException(nameof(amount)); Balance += amount; }}Multiple files and partial classes
Section titled “Multiple files and partial classes”Most projects put one main type per source file, but that is a convention rather than a C# requirement. partial allows one type declaration to span multiple files, commonly for generated code. The parts compile into the same type in the same assembly.
// Player.Core.cspublic partial class PlayerProfile { public string Name = "Alex"; }// Player.Stats.cs (another file, same namespace and assembly)public partial class PlayerProfile { public int Level = 1; }Deep dive: separate a blueprint from a real object
Section titled “Deep dive: separate a blueprint from a real object”What happens when new is evaluated?
Section titled “What happens when new is evaluated?”A class declaration describes a type: which data each instance holds and which operations it supports. new Player("Alex") allocates an object and invokes an instance constructor to establish its initial state. Two new expressions normally produce two independent objects, even when the arguments are identical. A variable of a class type usually holds a reference to an object rather than embedding a copy of the object’s fields.
var first = new Player("Alex");Player alias = first;var second = new Player("Alex");
alias.Level = 5;Console.WriteLine(first.Level); // 5: same objectConsole.WriteLine(second.Level); // 1: a different object
public sealed class Player{ public string Name { get; } public int Level { get; set; } = 1; public Player(string name) => Name = name;}This distinction matters when passing objects to methods: the method receives a copy of the reference, so it can mutate the same object. Reassigning its local parameter does not automatically replace the caller’s variable.
Constructor responsibilities
Section titled “Constructor responsibilities”A constructor should establish a valid, useful starting state: require essential parameters, validate them, assign read-only members and avoid leaving partially initialized objects. Constructors can be overloaded; : this(...) reuses another constructor, and : base(...) invokes a base-class constructor. Avoid hiding heavy I/O or network calls inside routine constructors, because object creation then becomes expensive and difficult to test.
Fields, properties and methods have different jobs
Section titled “Fields, properties and methods have different jobs”Use fields as internal storage, properties for controlled values, and methods for actions. A class should have one understandable responsibility rather than mixing input handling, saving files, UI drawing and combat calculations. Unity components follow the same separation, but a MonoBehaviour is normally added to a GameObject rather than instantiated using new.
Organizing a real project
Section titled “Organizing a real project”One public class per descriptive .cs file is a useful convention, not a universal C# language requirement. Several classes can share one file, and partial lets pieces of one type span files; tools and generated code commonly use it. Namespaces organize names, assemblies form compilation boundaries, and folders are a project convention rather than C# access controls.
When and why
Section titled “When and why”Give each class one understandable responsibility and establish required values in its constructor.
Common mistake
Section titled “Common mistake”Do not confuse a class with the .cs file containing it. Public mutable fields expose state that other code can change freely.
Try it yourself
Section titled “Try it yourself”Create a Book class whose constructor receives a title and exposes it read-only.
Reveal a solution
public class Book { public string Title { get; } public Book(string title) => Title = title; }.
