Classes and Objects in C#

In C#, classes are a fundamental concept that forms the blueprint for creating objects. Objects, in turn, are instances of classes that encapsulate both data and the methods that operate on that data. Let's explore how to define classes and create objects in C# with practical examples to solidify your understanding.

Defining a Class

A class in C# is defined using the class keyword followed by the class name. Class names should be descriptive and follow Pascal Case formatting. Here’s the simplest definition of a class:

public class Car
{
    // Fields
    public string Make;
    public string Model;
    public int Year;

    // Method
    public void DisplayInfo()
    {
        Console.WriteLine($"Car Make: {Make}, Model: {Model}, Year: {Year}");
    }
}

Breakdown of the Class Syntax

  1. Access Modifiers: The public keyword indicates that the class is accessible from other classes. You can also use private, protected, or internal depending on your needs.

  2. Fields: These are variables that hold the state of the class. In our Car class, Make, Model, and Year are fields that store properties of the car.

  3. Methods: Functions defined in a class are called methods. The DisplayInfo() method will display the car’s information when called.

Creating an Object

Once you have defined a class, you can create objects - instances of that class. Here’s how you can create an object of the Car class and access its members:

class Program
{
    static void Main(string[] args)
    {
        // Creating an object of the Car class
        Car myCar = new Car();

        // Setting the properties
        myCar.Make = "Toyota";
        myCar.Model = "Corolla";
        myCar.Year = 2022;

        // Calling the method
        myCar.DisplayInfo();
    }
}

Explanation of Object Creation

  1. Instantiating the Object: Car myCar = new Car(); creates a new instance of the Car class.

  2. Setting Properties: You can access and modify the fields directly using dot notation.

  3. Method Call: To invoke the method that is part of the object, you again use dot notation.

Now let’s build on this and explore constructors, an essential concept related to classes.

Constructors in C#

A constructor is a special method that is called when an object of a class is instantiated. It usually initializes object properties. In C#, if you do not define a constructor, the compiler automatically provides a default constructor. However, it’s common to define your own constructor to initialize the object with specific values.

Here’s how you can implement a constructor for our Car class:

public class Car
{
    // Fields
    public string Make;
    public string Model;
    public int Year;

    // Constructor
    public Car(string make, string model, int year)
    {
        Make = make;
        Model = model;
        Year = year;
    }

    // Method
    public void DisplayInfo()
    {
        Console.WriteLine($"Car Make: {Make}, Model: {Model}, Year: {Year}");
    }
}

Using the Constructor

With the constructor defined, you can now create an object of the Car class in a more concise way:

class Program
{
    static void Main(string[] args)
    {
        // Creating an object of the Car class using the constructor
        Car myCar = new Car("Toyota", "Corolla", 2022);

        // Calling the method
        myCar.DisplayInfo();
    }
}

In this case, when we create myCar, we directly pass values that initialize its properties.

Properties in Classes

While fields are public by default, it’s a good practice to use properties to encapsulate the data within a class. Properties allow for validation and encapsulation of your fields.

Here’s how you can modify the Car class to use properties:

public class Car
{
    // Auto-implemented properties
    public string Make { get; set; }
    public string Model { get; set; }
    public int Year { get; set; }

    // Method
    public void DisplayInfo()
    {
        Console.WriteLine($"Car Make: {Make}, Model: {Model}, Year: {Year}");
    }
}

Advantages of Properties

  • Encapsulation: You can add validation logic in the property setters to restrict invalid values.
  • Abstraction: Consumers of your class do not need to understand the underlying implementation.

Class Inheritance

Inheritance allows one class to inherit the properties and methods of another. This promotes code reuse and can make your code more maintainable.

Below is an example where we create a derived class:

public class ElectricCar : Car
{
    public int BatteryLife { get; set; }

    public ElectricCar(string make, string model, int year, int batteryLife)
        : base(make, model, year)
    {
        BatteryLife = batteryLife;
    }

    public void DisplayBatteryLife()
    {
        Console.WriteLine($"Battery Life: {BatteryLife} hours");
    }
}

Inheriting and Using the Derived Class

You can now create an instance of the ElectricCar class as follows:

class Program
{
    static void Main(string[] args)
    {
        ElectricCar myElectricCar = new ElectricCar("Tesla", "Model S", 2023, 12);

        myElectricCar.DisplayInfo(); // Calls the method from the base class
        myElectricCar.DisplayBatteryLife(); // Calls the method from the derived class
    }
}

Polymorphism and Overriding Methods

Polymorphism allows methods to do different things based on the object it is acting upon, even if they share the same name. In C#, we can achieve polymorphism through method overriding using the virtual and override keywords.

Let's extend our class structure to demonstrate this:

public class Car
{
    public virtual void StartEngine()
    {
        Console.WriteLine("Starting the car engine...");
    }
}

public class ElectricCar : Car
{
    public override void StartEngine()
    {
        Console.WriteLine("Starting the electric motor...");
    }
}

Using Polymorphism

You can create a method that accepts the base class type and calls the overridden method:

class Program
{
    static void Main(string[] args)
    {
        Car myCar = new Car();
        Car myElectricCar = new ElectricCar();

        myCar.StartEngine(); // Calls Car's implementation
        myElectricCar.StartEngine(); // Calls ElectricCar's implementation
    }
}

Conclusion

Classes and objects form the backbone of object-oriented programming in C#. By defining classes with fields, properties, methods, and constructors, you can build robust applications. Additionally, using concepts like inheritance and polymorphism will enhance your ability to create reusable and maintainable code.

With this knowledge, you're ready to implement classes and objects in your C# projects like a pro! Happy coding!