Classes and Objects
A class is a blueprint that describes the data (fields, properties) and behavior (methods) that its instances will have. An object is a concrete instance of that blueprint, allocated on the managed heap and accessed through a reference. C# is a class-based, object-oriented language: virtually everything you write — from a small data holder to a complex service — is expressed as a class or one of its relatives (struct, record, interface). Grasping the class/object distinction, and how references behave differently from the value types you may already know from earlier lessons, is foundational to everything else in C#'s object model.
Cricket analogy: The BCCI's official coaching manual for a fast bowler's action is the blueprint; Jasprit Bumrah himself, running in at the MCG, is the concrete instance built from it, occupying his own space on the field.
Declaring a class
A class declaration bundles fields (private storage), properties (controlled access to that storage), methods (behavior), and optionally nested types, all inside a named scope. By default, a class member is 'private' unless you mark it otherwise, following the principle of encapsulation: expose only what callers need. Fields typically back properties rather than being exposed directly, so validation or computed logic can run whenever a value is read or written.
Cricket analogy: A team's dressing room keeps strategy notes private by default, only sharing the final batting order (a controlled property) with the umpires, mirroring how private fields are hidden behind exposed properties.
public class BankAccount
{
private decimal _balance;
public string Owner { get; }
public decimal Balance => _balance;
public BankAccount(string owner, decimal openingBalance)
{
Owner = owner;
_balance = openingBalance;
}
public void Deposit(decimal amount)
{
if (amount <= 0) throw new ArgumentOutOfRangeException(nameof(amount));
_balance += amount;
}
public void Withdraw(decimal amount)
{
if (amount > _balance) throw new InvalidOperationException("Insufficient funds");
_balance -= amount;
}
}Creating and using objects
You create an object with the 'new' operator, which allocates memory on the heap, runs the constructor, and returns a reference to the new instance. That reference is what gets stored in a variable — the variable itself does not hold the object's data, it holds an address. Assigning one object variable to another copies the reference, so both variables point at the same underlying object; mutating through one is visible through the other. This is the crucial difference from value types like int or a struct, where assignment copies the entire value.
Cricket analogy: Handing a teammate your bat during a partnership doesn't clone it into two bats; both players are now referring to the same physical bat, so a nick in the willow is visible no matter who's holding it.
var account1 = new BankAccount("Priya", 500m);
var account2 = account1; // same object, not a copy
account2.Deposit(100m);
Console.WriteLine(account1.Balance); // 600 — account1 sees the change tooInstance members vs. the type itself
Fields, properties, and non-static methods belong to each individual object — every BankAccount has its own Owner and Balance. Static members, by contrast, belong to the class itself and are shared across all instances (covered in depth in the static-members topic). A well-designed class keeps its instance state private and exposes a minimal, coherent public surface — constructors to establish valid initial state, and methods/properties that maintain invariants (like never allowing a negative balance) rather than letting external code manipulate fields directly.
Cricket analogy: Each batter walking out has their own personal score and strike rate for the innings, but the stadium's shared scoreboard total belongs to the team as a whole, the way instance fields differ from static ones.
In C#, 'class' always produces a reference type, whereas 'struct' produces a value type. Java has no value-type equivalent for user-defined types (until recent JEP proposals), while C++ lets any class be allocated on the stack or heap depending on how you declare it — C# instead makes the choice explicit through the class/struct keyword.
A common beginner mistake is assuming '==' compares object contents. By default, '==' on a class compares references (identity), not field values — 'account1 == account2' is true only when both variables refer to the same object in memory, not merely equal-looking ones. Override Equals (or use a record) if value-based equality is desired.
- A class is a blueprint; an object is a runtime instance of that blueprint allocated on the heap.
- Class members default to private; expose behavior deliberately through public methods and properties.
- Object variables hold references, so assignment copies the reference, not the data.
- Constructors establish an object's valid initial state when 'new' is used.
- Instance members belong to each object; static members belong to the class itself.
- Default '==' on classes compares reference identity, not field-by-field value equality.
Practice what you learned
1. What does a C# variable of a class type actually store?
2. What happens when you assign one class-typed variable to another, e.g. 'b = a;'?
3. By default, what does '==' do when comparing two class instances (without an overload)?
4. What is the default accessibility of a member declared inside a class without an access modifier?
5. What triggers the allocation of a new object instance on the heap?
Was this page helpful?
You May Also Like
Constructors and Initialization
Explore how constructors establish an object's initial state, including constructor overloading, chaining with 'this'/'base', field initializers, and object initializer syntax.
Encapsulation and Access Modifiers
Understand how C#'s access modifiers — public, private, protected, internal, and their combinations — let you control visibility and enforce encapsulation boundaries.
Properties and Indexers
Explore how C# properties expose controlled field access through get/set accessors, and how indexers let custom types support array-like `obj[key]` syntax.
Inheritance in C#
Learn how C# classes derive from a single base class to reuse and extend behavior, including virtual/override methods, base member access, and sealing.
Related Reading
Related Study Notes in Programming
Browse all study notesApache Spark Study Notes
Programming · 30 topics
ProgrammingApache Flink Study Notes
Programming · 30 topics
ProgrammingHadoop Study Notes
Programming · 30 topics
ProgrammingSnowflake Study Notes
Programming · 30 topics
ProgrammingApache Airflow Study Notes
Programming · 30 topics
Programmingdbt (Data Build Tool) Study Notes
Programming · 30 topics