← Back to Articles         
finalizer and Dispose()

finalizer and Dispose()

Published on 12 Oct 2026     5 min read C#
Constructors, Properties & Methods
 

C# Methods and Resource Management

1. What are expression-bodied members?

Definition: Expression-bodied members allow you to write simple methods, properties, and constructors using the => operator instead of a traditional method body.

They make code shorter and more readable.

Example

public class Calculator
{
    // Normal method
    public int Add(int a, int b)
    {
        return a + b;
    }

    // Expression-bodied method
    public int Multiply(int a, int b) => a * b;
}

Usage:

Calculator calc = new Calculator();

Console.WriteLine(calc.Add(10, 20));      // 30
Console.WriteLine(calc.Multiply(10, 20)); // 200

Explanation

  • Add() uses the traditional method body with return.

  • Multiply() uses => to return the result directly.

  • Both approaches provide the same functionality.

Expression-bodied members also work with properties:

public string Name => "John";

Key Points

  • => is called the expression-body operator in this context.

  • Reduces boilerplate code.

  • Supports methods, properties, constructors, indexers, and other members.

  • Best suited for simple, single-expression operations.

  • Complex business logic is generally easier to maintain with traditional method bodies.

 

2. What are optional and named parameters?

Definition: Optional parameters allow you to omit arguments when calling a method. Named parameters allow you to pass arguments by their parameter names instead of relying only on their positions.

Example

public class Employee
{
    public void Display(
        string name,
        string department = "IT",
        int age = 25)
    {
        Console.WriteLine(
            $"{name} - {department} - {age}");
    }
}

Usage:

Employee emp = new Employee();

// Optional parameters
emp.Display("John");

// All parameters
emp.Display("David", "HR", 30);

// Named parameters
emp.Display(name: "Peter", age: 35);

Output:

John - IT - 25
David - HR - 30
Peter - IT - 35

Explanation

Optional parameters:

emp.Display("John");

Only the required name argument is provided. The compiler uses the default values for department and age.

Named parameters:

emp.Display(name: "Peter", age: 35);
  • name receives "Peter".

  • age receives 35.

  • department uses its default value "IT".

Key Points

  • Optional parameters must come after required parameters.

  • Optional parameters require compile-time constant defaults (with certain supported exceptions such as default).

  • Named parameters improve readability.

  • Named parameters allow you to skip optional parameters.

  • Both features help reduce unnecessary method overloads.

 

3. What are extension methods, and when should they be used?

Definition: Extension methods allow you to add new methods to existing types without modifying their source code or inheriting from them.

Extension methods are commonly used in LINQ and reusable helper functionality.

Example

Suppose you want to add a method to the string type that converts text to uppercase.

public static class StringExtensions
{
    public static string ToUpperText(this string value)
    {
        return value.ToUpper();
    }
}

Usage:

string name = "john";

string result = name.ToUpperText();

Console.WriteLine(result);

Output:

JOHN

Explanation

  • StringExtensions is a static class.

  • ToUpperText() is a static method.

  • this string value specifies that the method extends string.

  • You can call ToUpperText() as though it were an instance method of string.

Flow Diagram

string name = "john"
         |
         v
name.ToUpperText()
         |
         v
StringExtensions.ToUpperText(name)
         |
         v
value.ToUpper()
         |
         v
       "JOHN"

When should extension methods be used?

  • To add reusable helper methods to existing types.

  • To extend framework or third-party types without modifying them.

  • To create fluent APIs and readable method chains.

  • To implement custom LINQ-style operations.

Key Points

  • Extension methods must be declared in a non-generic static class.

  • Extension methods themselves must be static.

  • The first parameter uses the this keyword.

  • The namespace containing the extension method must be in scope.

  • Extension methods do not actually modify the original type.

  • Applicable instance methods take precedence over extension methods.

Real-world example: LINQ methods such as Where(), Select(), and OrderBy() are extension methods.

 

4. What is the difference between a finalizer and Dispose()?

Definition: Both are associated with resource cleanup, but they work differently.

  • Finalizer: Provides cleanup when the Garbage Collector determines that an object is eligible for finalization.

  • Dispose(): Allows resources to be released explicitly and deterministically.

Example

public class FileManager : IDisposable
{
    public void Dispose()
    {
        Console.WriteLine("Dispose called");
        GC.SuppressFinalize(this);
    }

    ~FileManager()
    {
        Console.WriteLine("Finalizer called");
    }
}

Usage:

using (FileManager file = new FileManager())
{
    Console.WriteLine("Working with file");
}

Output:

Working with file
Dispose called

Explanation

  1. A FileManager object is created.

  2. The application executes the code inside the using block.

  3. When execution leaves the block, Dispose() is called automatically.

  4. GC.SuppressFinalize(this) prevents the finalizer from running for that object.

Note: This is a demonstration of the cleanup lifecycle. A real implementation should release its owned resources inside Dispose(). Finalizers are generally needed only when a class directly owns unmanaged resources.

Flow Diagram

          Object Created
                |
        +-------+-------+
        |               |
        v               v
   using / Dispose   No explicit Dispose
        |               |
        v               v
  Dispose() called   Object becomes
        |            unreachable
        v               |
  Release resources     v
        |          Garbage Collector
        v               |
 Suppress finalizer     v
                   Finalizer may run
                       later

Differences

Feature

Finalizer

Dispose()

Execution

Managed by GC finalization

Explicit or using

Timing

Unpredictable

Deterministic

Interface

Not required

Usually IDisposable

Performance

Adds GC overhead

Generally more efficient

Purpose

Fallback for unmanaged cleanup

Timely resource cleanup

Syntax

~ClassName()

Dispose()

Key Points

  • Dispose() is the preferred way to release resources promptly.

  • Finalizers run at an unpredictable time and are not guaranteed to run at process shutdown.

  • using automatically calls Dispose(), even if an exception occurs inside the block.

  • IDisposable defines the Dispose() contract.

  • GC.SuppressFinalize(this) avoids unnecessary finalization when applicable.

  • For asynchronous cleanup, C# also supports IAsyncDisposable and await using.

 

Quick Interview Revision

Concept

Remember

Expression-bodied members

Use => for concise member implementations

Optional parameters

Provide default argument values

Named parameters

Pass arguments using parameter names

Extension methods

Add callable methods to existing types using this

Finalizer

GC-managed, nondeterministic cleanup

Dispose()

Explicit, deterministic resource cleanup

Important interview takeaway: Expression-bodied members, optional parameters, named parameters, and extension methods primarily improve code readability and reusability. Dispose() and finalizers concern resource lifetime and cleanup.

← Back to Articles