Top C# Interview Questions and Answers (2024)

author image Hirely
at 06 Jan, 2025

Question: What is the difference between an abstract class and an interface in C#?

Answer:

In C#, both abstract classes and interfaces are used to define contract-like structures that other classes can implement or inherit from. However, they have several key differences in terms of usage, behavior, and capabilities.

Here’s a detailed comparison:


1. Purpose:

  • Abstract Class:
    • An abstract class is a class that cannot be instantiated on its own. It provides a base for other classes to inherit from. It can contain both fully implemented methods (with code) and abstract methods (without code).
    • It is used when you have a common base class that should share some behavior across multiple derived classes while also enforcing certain methods to be implemented in the derived classes.
  • Interface:
    • An interface defines a contract that classes or structs must implement. It only contains method signatures, properties, events, or indexers (but no implementation). All methods defined in an interface are implicitly abstract and must be implemented by the classes that inherit the interface.
    • It is used to define a common set of operations that can be implemented by any class or struct, regardless of where the class is in the inheritance hierarchy.

2. Method Implementation:

  • Abstract Class:
    • Can have both abstract methods (without implementation) and concrete methods (with implementation).
    • Abstract methods must be implemented in the derived class, while concrete methods are inherited as-is or can be overridden.
  • Interface:
    • Can only have method declarations (i.e., signatures) without any implementation.
    • All methods in an interface are implicitly abstract, meaning they must be implemented by any class or struct that implements the interface.
// Abstract Class Example
public abstract class Animal
{
    public abstract void MakeSound();  // Abstract method
    public void Sleep()                // Concrete method
    {
        Console.WriteLine("Sleeping...");
    }
}

// Interface Example
public interface IAnimal
{
    void MakeSound();  // Only method signature, no implementation
}

3. Multiple Inheritance:

  • Abstract Class:
    • A class can inherit only one abstract class (C# does not support multiple inheritance for classes).
  • Interface:
    • A class or struct can implement multiple interfaces. This allows for more flexibility in defining behavior from multiple sources.
// Abstract Class Example: Single Inheritance
public abstract class Animal { }
public class Dog : Animal { }

// Interface Example: Multiple Inheritance
public interface IFlyable { void Fly(); }
public interface ISwimmable { void Swim(); }

public class Duck : IFlyable, ISwimmable
{
    public void Fly() { Console.WriteLine("Flying"); }
    public void Swim() { Console.WriteLine("Swimming"); }
}

4. Access Modifiers:

  • Abstract Class:
    • Can have access modifiers (like public, private, protected, etc.) for its methods, fields, and properties.
  • Interface:
    • Members of an interface are always public by default. You cannot specify any other access modifier for the methods, properties, or events defined in an interface.
// Abstract Class Example
public abstract class MyClass
{
    protected abstract void MyMethod();  // Can have protected or private methods
}

// Interface Example
public interface IMyInterface
{
    void MyMethod();  // Cannot specify access modifiers, always public
}

5. Fields and Properties:

  • Abstract Class:
    • Can have fields, properties, and constants in addition to methods.
    • Fields and properties can have different access levels (e.g., private, protected).
  • Interface:
    • Cannot contain any fields or implementation code.
    • Only method signatures, properties, events, and indexers are allowed, and they are implicitly public.
    • Interfaces cannot have instance fields.
// Abstract Class Example
public abstract class MyClass
{
    public int MyField;  // Can have fields
}

// Interface Example
public interface IMyInterface
{
    int MyProperty { get; set; }  // Can have properties, but no implementation
}

6. Constructor:

  • Abstract Class:
    • Can have constructors to initialize state when an object is created. These constructors are called when an object of a derived class is created.
  • Interface:
    • Cannot have constructors. Interfaces cannot be instantiated directly.
// Abstract Class Example
public abstract class Animal
{
    public Animal()  // Abstract class can have a constructor
    {
        Console.WriteLine("Animal Created");
    }
}

// Interface Example
public interface IAnimal
{
    // No constructor allowed
}

7. Usage Scenarios:

  • Abstract Class:
    • Use abstract classes when you have a common base class with shared implementation and also require derived classes to implement some abstract methods.
    • Ideal when you want to share common functionality but enforce implementation of specific methods.
  • Interface:
    • Use interfaces when you want to define a contract that can be implemented by any class or struct, regardless of where they are in the inheritance hierarchy.
    • Ideal for defining common functionality that can be shared across different class hierarchies.

8. Example of Abstract Class and Interface in Action:

// Abstract Class Example
public abstract class Animal
{
    public abstract void MakeSound(); // Abstract method
    public void Sleep() { Console.WriteLine("Sleeping..."); } // Concrete method
}

public class Dog : Animal
{
    public override void MakeSound() { Console.WriteLine("Bark!"); }
}

// Interface Example
public interface IFlyable
{
    void Fly(); // Method signature only
}

public class Bird : IFlyable
{
    public void Fly() { Console.WriteLine("Flying..."); }
}

In this example:

  • Animal is an abstract class that has both an abstract method (MakeSound()) and a concrete method (Sleep()).
  • IFlyable is an interface that requires implementing classes to define the Fly() method.
  • Dog inherits from Animal and implements the MakeSound() method.
  • Bird implements the IFlyable interface by providing the Fly() method.

Summary of Differences:

FeatureAbstract ClassInterface
InstantiationCannot be instantiated directlyCannot be instantiated directly
InheritanceSupports single inheritanceSupports multiple inheritance
MethodsCan have both abstract and concrete methodsAll methods are abstract by default
FieldsCan have fields and constantsCannot have fields or constants
PropertiesCan have properties with implementationCan have properties (no implementation)
Access ModifiersCan have access modifiers (public, private, etc.)All members are implicitly public
ConstructorsCan have constructorsCannot have constructors
Use CaseUse when sharing behavior and enforcing abstract methodsUse to define a contract for any class to implement

In conclusion, abstract classes are used for common functionality with optional method implementation, while interfaces define a strict contract for classes to follow, without any implementation.

Question: Why are delegates used in C#?

Answer:

In C#, delegates are used to represent references to methods with a specific parameter list and return type. Essentially, a delegate is a type-safe function pointer that allows methods to be passed as parameters, stored, and invoked dynamically at runtime. Delegates are an essential feature in C#, enabling a wide range of scenarios, especially in event handling, callbacks, and designing flexible and decoupled systems.

Here are the key reasons why delegates are used in C#:


1. Method References and Callbacks:

  • Delegates allow methods to be passed as arguments. You can pass a method as a parameter to another method without directly invoking it. This is useful when you need to pass behavior (i.e., a method) around your application for flexible execution.
  • Callback Mechanism: Delegates are often used in asynchronous programming to allow a method to call another method once an operation completes. The passed method (delegate) gets executed when the operation finishes.

Example:

public delegate void ProcessDelegate(string message);  // Delegate declaration

public class Processor
{
    public void ProcessData(ProcessDelegate callback)
    {
        Console.WriteLine("Processing data...");
        callback("Processing completed");
    }
}

public class Program
{
    static void Main()
    {
        Processor processor = new Processor();
        processor.ProcessData(CallbackMethod); // Pass the delegate (method reference)
    }

    static void CallbackMethod(string message)
    {
        Console.WriteLine(message);
    }
}

2. Event Handling:

  • Delegates are heavily used in C# for event handling. An event is a special kind of delegate that enables a publisher (the event sender) to notify one or more subscribers (event handlers) about an occurrence of a specific event. This is crucial in building decoupled systems, where the publisher does not need to know about the subscribers, making the code more modular and maintainable.
  • C# events are built on top of delegates and allow event-driven programming.

Example:

public class Alarm
{
    public delegate void AlarmHandler(string message);  // Delegate
    public event AlarmHandler OnAlarmTriggered;         // Event

    public void TriggerAlarm(string message)
    {
        OnAlarmTriggered?.Invoke(message);  // Trigger event
    }
}

public class Program
{
    static void Main()
    {
        Alarm alarm = new Alarm();
        alarm.OnAlarmTriggered += AlarmTriggeredHandler;  // Event subscription
        alarm.TriggerAlarm("Alarm Triggered!");           // Trigger event
    }

    static void AlarmTriggeredHandler(string message)
    {
        Console.WriteLine(message);
    }
}

3. Decoupling Code:

  • Delegates promote loose coupling between components. For instance, a method can execute logic that doesn’t require knowing about the details of other methods that may be called later. Delegates help you to define callbacks and event handlers without binding specific implementations, allowing for flexibility.
  • This flexibility allows you to change the behavior of your program dynamically, without modifying the method that invokes the delegate.

4. Multicast Delegates:

  • Multicast delegates allow you to associate multiple methods with a single delegate. When the delegate is invoked, all the methods in its invocation list are called in sequence. This feature is particularly useful for event handling, where multiple subscribers can react to the same event.

Example:

public delegate void Notify();  // Multicast delegate

public class Program
{
    static void Main()
    {
        Notify notifyDelegate = Method1;
        notifyDelegate += Method2;  // Add more methods to the delegate list

        notifyDelegate();  // Both Method1 and Method2 are called
    }

    static void Method1()
    {
        Console.WriteLine("Method 1 executed");
    }

    static void Method2()
    {
        Console.WriteLine("Method 2 executed");
    }
}

5. Anonymous Methods and Lambda Expressions:

  • Delegates are closely tied to anonymous methods and lambda expressions, which are shorthand ways of defining inline methods without needing to explicitly declare a method. This makes the code more concise and readable.
  • Lambda expressions often use delegates to create inline methods for passing around as arguments.

Example (Lambda Expression):

public delegate void PrintMessage(string message);

public class Program
{
    static void Main()
    {
        PrintMessage print = (message) => Console.WriteLine(message);
        print("Hello from Lambda Expression!");
    }
}

6. Functional Programming Paradigms:

  • In more advanced scenarios, delegates facilitate functional programming paradigms in C#, such as higher-order functions, where methods can be passed and returned like first-class citizens. This allows C# to support patterns such as map, filter, and reduce, making it versatile for more complex operations.

Example:

public delegate int MathOperation(int x, int y);

public class Calculator
{
    public int ExecuteOperation(MathOperation operation, int x, int y)
    {
        return operation(x, y);
    }
}

public class Program
{
    static void Main()
    {
        Calculator calculator = new Calculator();

        // Passing lambda expression to delegate
        MathOperation add = (x, y) => x + y;
        int result = calculator.ExecuteOperation(add, 5, 3);
        Console.WriteLine(result); // Output: 8
    }
}

7. Delegate Types:

  • In addition to custom delegates, C# also provides several built-in delegate types like Action, Func, and Predicate. These are predefined generic delegates that can be used directly without needing to explicitly declare your own delegates, making code more streamlined and reducing boilerplate.

  • Action: Represents a method that takes parameters but does not return a value.

  • Func: Represents a method that takes parameters and returns a value.

  • Predicate: A special case of Func that returns a boolean value.

Example:

// Using Action (no return type)
Action<string> greet = (name) => Console.WriteLine($"Hello, {name}!");
greet("John");

// Using Func (returns a value)
Func<int, int, int> add = (x, y) => x + y;
int sum = add(5, 3);
Console.WriteLine(sum); // Output: 8

Summary:

Delegates in C# are used for:

  1. Passing methods as arguments (callback functions).
  2. Event handling (binding events to methods).
  3. Decoupling components in a system, allowing dynamic method invocation.
  4. Multicasting (calling multiple methods with a single delegate).
  5. Supporting anonymous methods and lambda expressions for concise code.
  6. Facilitating functional programming patterns and more flexible code designs.

By allowing methods to be passed around, invoked dynamically, and bound to events, delegates are a powerful tool in C# for writing flexible, maintainable, and event-driven code.

Read More

If you can’t get enough from this article, Aihirely has plenty more related information, such as C# interview questions, C# interview experiences, and details about various C# job positions. Click here to check it out.

Related Posts

Trace Job opportunities

Hirely, your exclusive interview companion, empowers your competence and facilitates your interviews.

Get Started Now