← Open in the full interactive course (progress tracking, search & more)

Classes are the blueprints. Objects are the real things you build from them.

Think about a car. A car has a make, a model, a colour, an engine size, and a speed. It can accelerate, brake, and honk.

Now think about a specific car — your neighbour's red Tesla, for example. It has actual values for those attributes, and it can actually perform those actions.

In C#, the class is the blueprint — the description of what a car is and what it does. The object is the actual instance — your neighbour's red Tesla, with real data and real behaviour.

Classes and objects are the heart of object-oriented programming in C#. They let you model real-world things, organise code, and build applications that are easier to understand, maintain, and extend.

What Is It?

The Simple Explanation

A class is a template or blueprint. It defines the data (fields/properties) and behaviour (methods) that objects of that class will have.

An object is an actual instance of a class — a concrete thing that exists in memory with its own state.

The Technical Definition

A class in C# is a reference type that defines a data structure and the operations that can be performed on that data. It is the fundamental building block of object-oriented programming.

An object is an instance of a class — allocated on the managed heap, with its own copy of the instance fields declared by the class.

Class vs Object

Class = the blueprint. It exists in your source code.

Object = the building built from the blueprint. It exists in memory at runtime.

You can have one class and create many objects from it — just like one blueprint can build many houses.

Key facts:

Why Does It Exist?

The Problem

Without classes, your program's data and behaviour are scattered. You might have arrays of primitive values, and functions that operate on them. But as the system grows, it becomes hard to:

The Solution

Classes provide a way to encapsulate data and behaviour into a single unit. This gives us:

Big Picture

Here's how classes and objects relate to each other and to your application:

CLASSES & OBJECTS — THE BIG PICTURE
SOURCE CODE
class Car { ... }
COMPILER
creates type metadata
RUNTIME
new Car() → object
Car #1
"Red Tesla"
Speed: 0 → 60
Car #2
"Blue BMW"
Speed: 20 → 80
Car #3
"White Ford"
Speed: 0 → 45
… many more objects
One class → many objects, each with its own state

How It Works

Let's trace what happens when you define a class and create objects from it.

LIFECYCLE OF A CLASS & OBJECT
Step 1 — Define the class (blueprint)
public class Car { public string Model { get; set; } public int Speed { get; private set; } public void Accelerate() { Speed += 10; } }

This defines what a Car looks like: it has a Model, a Speed, and it can Accelerate().

Step 2 — Create an object (instance)
Car myCar = new Car(); myCar.Model = "Tesla Model 3";

The new keyword allocates memory on the heap, initialises the object, and returns a reference. Now myCar points to a real Car object in memory.

Step 3 — Invoke behaviour on the object
myCar.Accelerate(); // Speed becomes 10 myCar.Accelerate(); // Speed becomes 20 Console.WriteLine(myCar.Speed); // 20

Calling a method on the object runs the behaviour defined in the class, using the object's own data.

Step 4 — More objects, independent state
Car anotherCar = new Car(); anotherCar.Model = "BMW i4"; anotherCar.Accelerate(); // Speed: 10 // myCar.Speed is still 20 — independent!

Each object has its own copy of the instance data. Changing one does not affect the other.

Step 5 — Object lifetime

Simple Example

Let's build a simple Person class and create objects from it.

public class Person { // Fields private string _name; private int _age; // Constructor public Person(string name, int age) { _name = name; _age = age; } // Properties public string Name => _name; public int Age => _age; // Method public void Introduce() { Console.WriteLine($"Hi, I'm {_name} and I'm {_age} years old."); } // Method with behaviour public void HaveBirthday() { _age++; Console.WriteLine($" {_name} is now {_age}!"); } } // Usage Person alice = new Person("Alice", 30); Person bob = new Person("Bob", 25); alice.Introduce(); // Hi, I'm Alice and I'm 30 years old. bob.Introduce(); // Hi, I'm Bob and I'm 25 years old. alice.HaveBirthday(); // Alice is now 31! bob.HaveBirthday(); // Bob is now 26! Console.WriteLine($"{alice.Name} is {alice.Age}"); // Alice is 31

Code → Meaning → Result

Real-World Example

Imagine an e-commerce system that manages orders. Each order has items, a total, and a status. Here's how you might model this:

public class OrderItem { public string ProductName { get; set; } public int Quantity { get; set; } public decimal UnitPrice { get; set; } public decimal Total => Quantity * UnitPrice; } public class Order { private List<OrderItem> _items = new(); public int OrderId { get; set; } public DateTime OrderDate { get; set; } public string CustomerName { get; set; } public string Status { get; private set; } = "Pending"; public IReadOnlyList<OrderItem> Items => _items; public void AddItem(OrderItem item) { _items.Add(item); } public decimal TotalAmount => _items.Sum(i => i.Total); public void Ship() { if (Status != "Pending") throw new InvalidOperationException("Order already processed."); Status = "Shipped"; } public void Deliver() { if (Status != "Shipped") throw new InvalidOperationException("Order must be shipped first."); Status = "Delivered"; } } // Usage in a real application: var order = new Order { OrderId = 1001, OrderDate = DateTime.UtcNow, CustomerName = "Jane Doe" }; order.AddItem(new OrderItem { ProductName = "Laptop", Quantity = 1, UnitPrice = 1200.00m }); order.AddItem(new OrderItem { ProductName = "Mouse", Quantity = 2, UnitPrice = 25.99m }); Console.WriteLine($"Order total: {order.TotalAmount:C}"); // $1,251.98 order.Ship(); order.Deliver(); Console.WriteLine($"Status: {order.Status}"); // Delivered

In this example:

Analogy

Class = Blueprint, Object = House

A class is like an architect's blueprint for a house. The blueprint specifies:

An object is the actual house built from that blueprint. You can build many houses from the same blueprint:

The blueprint doesn't change when you paint one house red. Each object is independent.

Under the Hood

What actually happens inside the .NET runtime when you define a class and create objects?

INTERNAL VIEW — CLASSES & OBJECTS
1. TYPE DEFINITION
2. OBJECT ALLOCATION
3. CONSTRUCTOR EXECUTION
4. METHOD CALLS
5. GARBAGE COLLECTION

Common Confusion

1. Class vs Object

This is the most common confusion. A class is the definition — it's like the text of a recipe. An object is the actual cake you bake — it exists in the real world (memory).

Class
Object

2. class vs struct

A class is a reference type (stored on the heap; passed by reference). A struct is a value type (stored on the stack or inline; passed by value). Classes are used for complex objects with behaviour; structs are used for small, simple data containers.

3. Fields vs Properties

A field is a variable directly stored in the object. A property is a pair of methods (getter/setter) that control access to a field. Properties allow you to add logic (validation, notifications) while keeping the public API stable.

public class Example { private int _value; // field public int Value // property { get => _value; set { if (value < 0) throw new ArgumentException("Must be non-negative"); _value = value; } } }

4. Static vs Instance

Instance members belong to a specific object. Static members belong to the class itself — they are shared across all objects and exist even if no objects are created.

public class Counter { public int InstanceCount; // each object has its own public static int TotalCreations; // shared across all objects public Counter() { InstanceCount = 0; TotalCreations++; } }

Common Mistakes

Mistake 1 — Forgetting to use new

Wrong:

Person p; // p is null — no object exists! p.Introduce(); // NullReferenceException!

Correct:

Person p = new Person("Alice", 30); p.Introduce(); // Works!

Mistake 2 — Confusing static and instance

Wrong:

Console.WriteLine(Counter.TotalCreations); // OK, static Console.WriteLine(Counter.InstanceCount); // Error! Can't access instance member from class

Correct:

var c = new Counter(); Console.WriteLine(c.InstanceCount); // OK, instance Console.WriteLine(Counter.TotalCreations); // OK, static

Mistake 3 — Exposing mutable collections directly

Wrong:

public class Order { public List<OrderItem> Items { get; set; } // Anyone can modify! }

Correct:

public class Order { private readonly List<OrderItem> _items = new(); public IReadOnlyList<OrderItem> Items => _items; // Read-only view public void AddItem(OrderItem item) => _items.Add(item); }

Mistake 4 — Using == for object equality incorrectly

Wrong:

Person a = new Person("Alice", 30); Person b = new Person("Alice", 30); Console.WriteLine(a == b); // False — different objects, even if data is same

Correct:

Console.WriteLine(a.Name == b.Name && a.Age == b.Age); // True // Or override Equals and == in your class for value equality

When Should I Use It?

Use classes when:

Consider records (record) when:

When classes might be overkill:

Mental Model

Class = the blueprint
Object = the real thing built from the blueprint
new = the construction crew that builds the object
Field = a piece of data inside the object
Method = an action the object can perform
Property = a controlled way to access data
Constructor = the setup instructions when building

Remember:
· One class, many objects
· Each object has its own state
· Objects are independent
· Static members are shared across all objects

Key Takeaway


Check Your Understanding

You've seen how classes define blueprints and objects are the real instances. Let's test your understanding.

1. What is the difference between a class and an object?

Show answer

Correct: B

Why B is correct: A class is the definition (the blueprint) that describes what data and behaviour an object will have. An object is a concrete instance of that class — a real thing in memory with its own state.

Why A is incorrect: Both classes and objects are reference types (stored on the heap in .NET). The storage location depends on the type, not the class/object distinction.

Why C is incorrect: Both classes and objects have data and behaviour. A class defines both; an object has both.

Why D is incorrect: You use new to create objects from a class. The class itself is defined in source code.

Reinforcement: Class = blueprint, Object = building built from that blueprint.

2. Given the following class, what is the output?

public class Counter { public int Value = 0; public static int Total = 0; public Counter() { Total++; } public void Increment() { Value++; Total++; } } var a = new Counter(); var b = new Counter(); a.Increment(); b.Increment(); b.Increment(); Console.WriteLine($"{a.Value} {b.Value} {Counter.Total}");
Show answer

Correct: A — 1 2 6

Why A is correct:

  • Two objects are created → each constructor increments Total to 2.
  • a.Increment()a.Value = 1, Total = 3.
  • b.Increment()b.Value = 1, Total = 4.
  • b.Increment()b.Value = 2, Total = 5.
  • Total count: 2 (constructors) + 3 (increments) = 6.

Why B, C, D are incorrect: They miscount the static Total increments. The static field is shared and incremented in every constructor and every Increment() call.

Reinforcement: Static members belong to the class, not to individual objects. They are shared across all instances.

3. Which of the following correctly demonstrates encapsulation?

Show answer

Correct: B

Why B is correct: Encapsulation means hiding internal details and controlling access through a public interface. Making fields private and exposing them via properties or methods with validation is the textbook way to achieve encapsulation.

Why A is incorrect: Making all fields public breaks encapsulation — external code can directly modify the object's state, bypassing any validation or logic.

Why C is incorrect: A class with only public fields and no methods is a data container, not an encapsulated object.

Why D is incorrect: A class with no fields and only static methods isn't an object-oriented design — it's more like a module or utility class.

Reinforcement: Encapsulation = hide internal state, expose controlled public API.

4. What does the following code print?

public class Person { public string Name { get; set; } public Person(string name) => Name = name; public void ChangeName(string newName) => Name = newName; } Person p1 = new Person("Alice"); Person p2 = p1; p2.ChangeName("Bob"); Console.WriteLine(p1.Name);
Show answer

Correct: B — Bob

Why B is correct: Classes are reference types. p2 = p1 copies the reference, not the object. Both variables point to the same Person object. Changing the name through p2 modifies the same object that p1 references, so p1.Name is also "Bob".

Why A is incorrect: This would be true if Person were a struct (value type) where assignment copies the data. But class is a reference type.

Why C is incorrect: The object is never set to null.

Why D is incorrect: This is perfectly valid code and will not throw an exception.

Reinforcement: With reference types (classes), assignment copies the reference, not the object. Multiple variables can point to the same object.

5. Which of the following is a valid reason to use a private field with a public property instead of a public field?

Show answer

Correct: B

Why B is correct: A property can contain logic in its getter and setter. This lets you validate values, raise events, log changes, or compute derived values — all without changing the public API.

Why A is incorrect: Properties have a slight overhead compared to field access (though it's usually negligible). They don't make code run faster.

Why C is incorrect: Properties have no effect on garbage collection. Objects are collected when unreferenced.

Why D is incorrect: Properties do not automatically provide thread safety. You still need locks or other synchronization if multiple threads access the same object.

Reinforcement: Use properties to encapsulate access to fields — they give you a control point for validation, logging, and future changes.

You now have a solid understanding of classes and objects — the foundational building blocks of object-oriented programming in C#!


dotnetmadeeasy.com — Learn C# and .NET, the right way.