Oop
By the end of this lesson you'll be able to design your own types — bundling data and behaviour into classes , building objects from them, initialising them with constructors, and protecting their data with encapsulation. This is the way real C# programs are organised.
Learn Python, JavaScript, Java and more with free interactive lessons, real projects and AI-powered help. Beginner-friendly.
Part of the free C# course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.
A class is like an architectural blueprint for a house. It defines what rooms exist, where the doors go, and how the plumbing works — but it's not a house you can live in. An object is an actual house built from that blueprint. You can build hundreds of houses from one blueprint, each with its own paint colour (field values), yet they all share the same structure (methods and properties). A constructor is the building crew that sets each house up the day it's finished. And encapsulation is the walls and the wiring behind them: you flick the light switches (public methods), but you can't grab the live wires directly (private fields).
Object-Oriented Programming (OOP) is a way of organising code around objects — units that bundle data (what something is ) and behaviour (what something does ). Instead of one long script, you model your program as a set of cooperating objects, much like the real world.
C# is built around OOP — nearly everything lives inside a class. There are four classic pillars:
This lesson covers the foundations and the first pillar — encapsulation — alongside classes, objects, constructors, properties, and static members. These are the building blocks of every C# project from here on.
If you don't write a modifier on a class member, it defaults to private . Get into the habit of being explicit — it makes your intent obvious to the next reader.
1. Classes and Objects
A class is the blueprint — it describes the fields (the data each object holds) and the methods (what each object can do). An object is a specific thing built from that blueprint with its own values; you create one with the new keyword. The class is written once; you can build as many objects from it as you like, and each keeps its own data. Read this worked example, run it, then you'll finish a class yourself.
Your turn. The Rectangle class below is almost complete — it just needs a second field and a one-line method body. Fill in the two ___ blanks, then run it.
2. Constructors & this
Setting every field by hand after new is tedious and easy to forget — leaving an object half-built. A constructor fixes that: it's a special method with the same name as the class that runs automatically when you write new ClassName(...) , so you create and initialise the object in one line. Inside it, this means "the object being built right now" — handy when a parameter has the same name as a field ( this.Brand = brand; ).
Now you try. Finish the Dog constructor so it stores the name, then create a dog and make it bark. Fill in the three ___ blanks:
3. Encapsulation — Protecting Data
Encapsulation means hiding a class's data behind a controlled gate. You mark fields private so outside code can't touch them directly, and you offer public methods as the only way in. Those methods can enforce the rules — a bank account can refuse a negative deposit or an overdraft. The payoff is twofold: invalid data is impossible, and you can change how the class works inside without breaking any code that uses it.
4. Properties — Fields vs Properties
A field is raw stored data; a property looks like a field from outside but runs code when read or written, which lets you add validation without changing how callers use it. An auto-property — public string Name {' '} — is the everyday default and the compiler creates the hidden storage for you. For checks, use a full property with a private backing field; for values derived on the fly, use a computed property with => ; and leave out set to make a property read-only.
It's tempting to just write public string name; and be done. The trouble is the day you need a rule — "names can't be empty" — you'd have to add validation, which means turning the field into a property, which changes its type of member and can break code (and reflection/serialisation) that relied on it being a field.
A property future-proofs you: it already looks like obj.Name = "Al"; to callers, but you can slip validation into the setter later without changing a single line of calling code .
Convention: properties are PascalCase ( FirstName ), private backing fields are camelCase or underscore-prefixed ( firstName or _firstName ).
5. Static vs Instance Members
Instance members belong to each object — every car has its own brand. Static members belong to the class itself and are shared by every object — perfect for things like "how many cars exist in total." You access an instance member through an object ( car1.Brand ) and a static member through the class name ( Counter.GetTotalCount() ). If a value should be the same for every object, make it static; if each object needs its own copy, keep it instance.
Here's a small but real class that uses everything from this lesson at once — a constructor, a read-only property, a private field guarded by a public method, a computed property, and a static counter shared across every playlist. You understand every line now.
Notice PlaylistsMade is static with a private set — outside code can read the total but only the class itself can change it. That's encapsulation applied to a static member.
Q: What's the actual difference between a class and an object?
A class is the design — written once, it lists the fields and methods. An object is a real thing built from that design with new , holding its own values. Blueprint vs house: one blueprint, many houses.
Q: When should I use a field versus a property?
Use a private field for internal storage, and expose data through a property rather than a public field. Properties look like fields to callers but let you add validation or change the implementation later without breaking anyone.
You used an object variable that was never assigned with new , so it points at null . Create the object first ( var c = new Car(...); ) before calling its methods or reading its data.
Q: When should something be static instead of instance?
Make it static when the value or behaviour belongs to the class as a whole and is shared by every object — like a running count of how many objects exist, or a utility method that doesn't need any object's data. If each object needs its own copy, keep it instance.
No blanks this time — just a brief and an outline to keep you on track. Build a BankAccount class with a private balance, a constructor, Deposit and Withdraw methods that enforce the rules, and a way to read the balance — then exercise it in Main . Run it and check your output against the expected line in the comments.
Practice quiz
What is the relationship between a class and an object?
- They are identical
- An object is a blueprint; a class is an instance
- A class is a blueprint; an object is an instance built from it
- A class can have only one object
Answer: A class is a blueprint; an object is an instance built from it. A class is the design (blueprint); an object is a real instance created from it with new.
Which keyword creates an object from a class?
- new
- create
- make
- object
Answer: new. The new keyword builds an instance, e.g. var c = new Car();.
What is special about a constructor?
- It returns a value
- It must be private
- It is called manually after new
- It has the same name as the class and runs when you write new
Answer: It has the same name as the class and runs when you write new. A constructor shares the class's name, has no return type, and runs automatically on new.
What does the this keyword refer to inside a method?
- The base class
- The current object instance
- A static field
- The class itself
Answer: The current object instance. this means the object the method is being called on — useful when a parameter shares a field's name.
What does the private access modifier mean?
- Accessible only inside the same class
- Accessible anywhere
- Accessible by derived classes
- Accessible within the project
Answer: Accessible only inside the same class. private members can be touched only by code inside the same class — the core of encapsulation.
What is an auto-property like public string Name { get; set; } ?
- A private field
- A static method
- A property whose backing storage the compiler creates for you
- A constructor
Answer: A property whose backing storage the compiler creates for you. An auto-property has the compiler generate the hidden backing field automatically.
A property with a get but no set is what?
- Write-only
- Read-only (assignable only in the constructor)
- Static
- Computed
Answer: Read-only (assignable only in the constructor). With only a get, the property is read-only and can be set just in the constructor.
What does a static member belong to?
- Each individual object
- Only the constructor
- The base class only
- The class itself, shared by all objects
Answer: The class itself, shared by all objects. A static member belongs to the class and is shared across every instance.
How do you call a static method like GetTotalCount on class Counter?
- counter1.GetTotalCount()
- Counter.GetTotalCount()
- new Counter().GetTotalCount()
- static GetTotalCount()
Answer: Counter.GetTotalCount(). Static members are accessed through the class name: Counter.GetTotalCount().
What is the main benefit of using a property instead of a public field?
- It runs faster
- It uses less memory
- You can add validation later without changing calling code
- It is always static
Answer: You can add validation later without changing calling code. A property looks like a field to callers but lets you slip in validation or change the implementation later.