Advertisement
Intermediate C# Lesson 2 of 10

Lesson 2: Fields, Properties & Methods in C#

In Lesson 1, we learned that classes bundle state (data) and behavior (methods) together. Now we'll dive deeper into the building blocks: fields hold data, properties control access to that data, and methods define what a class can do. This lesson covers the differences between them and when to use each one.

Advertisement

Fields vs Properties

A field is a variable inside a class. A property wraps a field with getter and setter logic, giving you control over how data is accessed. In modern C#, properties are preferred because they provide encapsulation without the boilerplate.

Old Way: Bare Fields

public class BankAccount
{
    // Public field — anyone can read or modify directly
    public string AccountHolder;
    public decimal Balance;
}

The problem: no validation. You can set balance to a negative number, which is nonsense for a bank account.

Better Way: Properties with Getters & Setters

public class BankAccount
{
    private decimal _balance;  // Private field (underscore by convention)

    // Property with validation
    public decimal Balance
    {
        get { return _balance; }
        set
        {
            if (value >= 0)
                _balance = value;
            else
                Console.WriteLine("Error: balance cannot be negative");
        }
    }
}

Now setting a negative balance is rejected. The field is hidden (private), and the property controls access.

Auto-Properties (Modern Approach)

When you don't need complex logic, C# offers auto-properties — a shorthand that reduces boilerplate:

public class Person
{
    // Auto-property: compiler creates a hidden backing field
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public int Age { get; set; }
}

// Usage
var person = new Person { FirstName = "John", LastName = "Doe", Age = 30 };

The compiler generates the backing field automatically. This is clean and readable.

Read-Only Properties

Use an init accessor if a property should be set only during construction:

public class Employee
{
    public int EmployeeId { get; init; }  // Can only set during construction
    public string Name { get; set; }      // Can be changed anytime
}

// Usage
var emp = new Employee { EmployeeId = 101, Name = "Alice" };
emp.Name = "Alice Smith";         // ✓ OK
emp.EmployeeId = 999;             // ✗ Compile error!

💡 Rule of Thumb: Use auto-properties by default. Reach for explicit getters/setters only when you need validation or side effects (e.g., logging).

Methods: Defining Class Behavior

A method is a function that belongs to a class. Methods define what actions objects of that class can perform. The syntax follows this pattern:

public class Calculator
{
    // Method with parameters and return type
    public int Add(int a, int b)
    {
        return a + b;
    }

    // Method with no parameters
    public void PrintHello()
    {
        Console.WriteLine("Hello!");
    }

    // Method with no return type (void)
    public void Greet(string name)
    {
        Console.WriteLine($"Hi, {name}!");
    }
}

// Usage
var calc = new Calculator();
int result = calc.Add(5, 3);       // result = 8
calc.PrintHello();                  // Output: Hello!
calc.Greet("Alice");                // Output: Hi, Alice!

Method Overloading

Methods in the same class can have the same name if they differ in parameter count or parameter types. This is called overloading:

public class Printer
{
    // Overload 1: takes an int
    public void Print(int value)
    {
        Console.WriteLine($"Integer: {value}");
    }

    // Overload 2: takes a string
    public void Print(string text)
    {
        Console.WriteLine($"Text: {text}");
    }

    // Overload 3: takes two strings
    public void Print(string first, string second)
    {
        Console.WriteLine($"{first} {second}");
    }
}

// Usage — the right method is called based on arguments
var printer = new Printer();
printer.Print(42);              // Calls Print(int)
printer.Print("Hello");         // Calls Print(string)
printer.Print("Hello", "World"); // Calls Print(string, string)

Static vs Instance Members

By default, fields and methods belong to objects (instance members). Static members belong to the class itself — all instances share the same static field:

public class Counter
{
    // Static field — shared by all instances
    public static int TotalCount = 0;

    // Instance field — each object has its own
    public int IndividualCount = 0;

    public void Increment()
    {
        TotalCount++;
        IndividualCount++;
    }
}

// Usage
var counter1 = new Counter();
var counter2 = new Counter();

counter1.Increment();  // TotalCount = 1, counter1.IndividualCount = 1
counter2.Increment();  // TotalCount = 2, counter2.IndividualCount = 1

Console.WriteLine(Counter.TotalCount);     // Output: 2 (shared)
Console.WriteLine(counter1.IndividualCount); // Output: 1
Console.WriteLine(counter2.IndividualCount); // Output: 1

Static Methods

Static methods perform work that doesn't depend on instance data. Common use: utility functions.

public class MathUtils
{
    // Static method — can be called without creating an object
    public static int Square(int x)
    {
        return x * x;
    }

    public static double CircleArea(double radius)
    {
        return Math.PI * radius * radius;
    }
}

// Usage
int result = MathUtils.Square(5);           // 25
double area = MathUtils.CircleArea(3.0);   // ≈ 28.27
Advertisement

🧠 Quick Check — Lesson 2

Which of the following is the best practice in modern C# for simple data with no validation logic?

Lesson Summary

✅

Fields are variables; properties wrap fields with getter/setter logic for encapsulation.

✅

Auto-properties reduce boilerplate: public string Name { get; set; }

✅

Use the init accessor to create read-only-after-construction properties.

✅

Methods define behavior. Use them to encapsulate logic and actions that objects can perform.

✅

Method overloading lets you reuse the same method name with different parameters.

✅

Static members belong to the class; instance members belong to objects. Use static for shared or utility code.

Up Next

Lesson 3: Constructors & Object Creation

Next Lesson →