C#
Completed
-
Section 1: Getting Started
-
Section 2: Core Syntax
-
Section 3: Object-Oriented C#
-
Section 4: Working with Data
-
Section 5: Error Handling
-
Section 6: Delegates and Events
-
Section 7: Async Programming
-
Section 8: More Language Features
-
Section 9: File I/O and Serialization
-
Section 10: Networking in .NET
-
Section 11: The .NET Ecosystem
-
Section 12: Memory and Performance
-
Section 13: Concurrency Beyond Async
-
Section 14: Reflection and Attributes
-
Section 15: Testing and Best Practices
-
Section 16: Design Patterns in C#
-
Section 17: Standard Library Deep Dive
-
Section 18: Data Structures and Algorithms in C#
-
Section 19: GUI and Desktop Development Overview
-
Section 20: Practical Projects
-
Section 21: More Practice Exercises
-
Section 22: More Standard Library and Text Processing
-
Section 23: More Design Patterns
-
Section 24: More Projects
-
Section 25: Interview Practice
-
Section 26: C# Keywords Reference (Modifiers)
-
Section 27: C# Keywords Reference (Statements)
-
Section 28: C# Keywords Reference (Operators)
-
Section 29: BCL: System.Collections.Generic
-
Section 30: BCL: System.Linq
-
Section 31: BCL: System.Threading
-
Section 32: BCL: System.IO
-
Section 33: BCL: System.Text and System.Text.Json
-
Section 34: BCL: System.Net.Http
-
Section 35: C# Language Specification Topics
-
Section 36: More Practice Exercises
-
Section 37: More Async Patterns
-
Section 38: More BCL: System.Reflection and System.Diagnostics
-
Section 39: Nullable Reference Types In Depth
-
Section 40: C# Records and Pattern Matching In Depth
-
Section 41: Dependency Injection Deep Dive
-
Section 42: More Interview and Whiteboard Practice
23: Properties, Fields, and Auto-Properties
Why can't I just make my variables public?
It's tempting. When you're first starting out, writing public int Health; feels faster than writing a whole property. But here is the problem: you're giving the rest of your program a blank check to mess with your object's internal state. If your Player class has a public health field, any other piece of code can set that health to -1,000,000 or 999,999,999, and your class has no way to stop it or react to it.
By using a property, you create a "gatekeeper." You keep the actual data (the field) private and expose a property that controls how that data is read or changed. I always tell my juniors: fields are for storage, properties are for access.
public class Player
{
// This is a field. Private means it's hidden from the outside world.
private int _health = 100;
// This is the property. It's the public "face" of the field.
public int Health
{
get { return _health; }
set
{
// Now we have a place to put logic!
// We can prevent health from going below 0.
if (value < 0) _health = 0;
else _health = value;
}
}
}
What exactly is a "backing field" and do I always need one?
In the example above, _health is what we call a backing field. It's the actual spot in memory where the value lives. The property Health doesn't actually "hold" the value; it just provides the logic to get it out or put it in.
Do you always need one? No. Most of the time, you don't need that custom logic in the setter. You just want a value that can be read and written. Writing out a private field and a full property every single time is tedious and makes your files feel cluttered. That's where auto-properties come in.
If I'm not adding logic, what's the point of an auto-property?
You'll see this syntax everywhere: public string Name { get; set; }. This is an auto-property. When you write this, the C# compiler actually creates a hidden, private backing field for you behind the scenes. You don't see it, but it's there.
You might wonder, "If it's just doing the same thing as a public field, why bother?" Because of future-proofing. If you start with an auto-property and realize six months from now that you need to add validation (like making sure the name isn't empty), you can convert it to a full property with a backing field without breaking any other code that uses your class. If you had used a public field, changing it to a property would be a "breaking change" for anyone using your library.
public class Player
{
// Clean, short, and professional.
public string Username { get; set; }
// I can still have my complex property right next to it.
public int Health { get; set; } = 100;
}
How do I make a property that others can read, but not change?
This is one of the most common patterns I use. Often, you want the rest of the game to know what level a player is, but you don't want some random UI script to be able to set the player's level to 99.
You can do this by adding an access modifier to the setter. By marking the setter as private, you're telling C#: "Anyone can see this value, but only code inside this class can change it."
public class Player
{
// Read-only to the outside world, writable inside the class.
public int Level { get; private set; } = 1;
public void GainExperience()
{
// This works because we are inside the class.
Level++;
}
}
// In another class:
// player.Level = 10; // This would now cause a compiler error!
📋 Practical Task
Exercise: Implementing a Secure Wallet System
You are building a Wallet class for a digital store. Your goal is to ensure that the wallet's balance cannot be manipulated directly and cannot possibly be negative.
- Create a
Walletclass. - Add a private field to store the balance (e.g.,
_balance). - Create a public property called
Balance. Thegetshould return the balance, but thesetshould only update the balance if the provided value is 0 or greater. If the value is negative, it should be ignored. - Add an auto-property called
OwnerNamethat can be read and written by anyone. - Add a property called
WalletIdthat can be read by anyone, but can only be set within theWalletclass (private setter). - In your
Mainmethod, try to set the balance to a negative number and verify that it stays at its default value.
There are no comments for now.