Best 75 C# Interview Questions and Answers for Experienced Professionals – 2024

Are you a C#.Net experienced professional looking for some C# interview questions? This tutorial discusses top C# interview questions and answers for experienced professionals. These more than 50 C# interview questions and answers will help you prepare for your upcoming interview.

After working for more than 15 years in Microsoft technologies, especially in Asp.Net and C#.Net, I thought I would add the list of C#.Net interview questions and answers for senior professionals. It will cover:

  • c# tricky interview questions and answers for experienced
  • c# scenario based interview questions for experienced
  • c# interview questions for 10 years experience

But if you are a beginner in C#, check out Top 51 Best C# Interview Questions and Answers for Freshers.

Table of Contents

C# Interview Questions and Answers for Experienced Professionals

Here is the list of interview questions and answers for experienced professionals for C# professionals.

1. What is C#? and Explain the features of C#

C# is a modern, object-oriented programming language developed by Microsoft. It is part of the .NET framework and is used for developing Windows applications, web applications, and more.

Some features of C# include:

  • Simple and modern syntax
  • Type safety
  • Automatic memory management
  • Rich library of classes and functions
  • Support for object-oriented programming concepts like inheritance, polymorphism, and encapsulation

2. What is the difference between C# and Java?

C# and Java are similar in many ways, as they are both object-oriented programming languages with similar syntax. However, there are some differences, such as:

  • C# is part of the .NET framework, while Java is part of the Java platform
  • C# supports properties and indexers, while Java does not
  • C# has a more extensive library of classes and functions compared to Java

3. Explain the different types of data types in C#

C# supports a wide range of data types, including:

  • Value types: int, float, char, etc.
  • Reference types: string, array, etc.
  • User-defined types: classes, structures, enums, etc.

4. How does C# handle exceptions?

C# uses a try-catch-finally block to handle exceptions. The try block contains the code that may throw an exception, the catch block contains the code that will be executed if an exception is thrown, and the finally block contains the code that will be executed regardless of whether an exception is thrown or not.

Here’s an example of how to handle an exception in C#:

try
{
    // Code that may throw an exception
}
catch (Exception e)
{
    // Code that will be executed if an exception is thrown
    Console.WriteLine(e.Message);
}
finally
{
    // Code that will be executed regardless of whether an exception is thrown or not
}

5. What is the difference between a class and a struct in C#?

A class is a reference type, while a struct is a value type. This means that when you create an instance of a class, you are creating a reference to the object in memory, while when you create an instance of a struct, you are creating a copy of the object.

6. What is polymorphism in C#?

Polymorphism allows methods to do different things based on the object it is acting upon, even though they share the same name.

Here’s an example of polymorphism in C#:

class Animal
{
    public virtual void MakeSound()
    {
        Console.WriteLine("Some sound");
    }
}

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

7. How does C# support polymorphism?

C# supports polymorphism through the use of virtual and override keywords. The virtual keyword is used to declare a method that can be overridden in a derived class, and the override keyword is used to declare a method that overrides a virtual method in a base class.

Here’s an example of how to use polymorphism in C#:

class Animal
{
    public virtual void MakeSound()
    {
        Console.WriteLine("Animal makes a sound");
    }
}

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

class Cat : Animal
{
    public override void MakeSound()
    {
        Console.WriteLine("Cat meows");
    }
}

8. What is encapsulation in C#?

Encapsulation is one of the four fundamental OOP concepts in C#. The other three are inheritance, polymorphism, and abstraction. Encapsulation is the technique of making the fields in a class private and providing access to them via public methods. It’s a protective barrier that keeps the data safe within the object and prevents outside code from directly accessing it.

Here’s an example of how to use encapsulation in C#:

class Person
{
    private string name;
    private int age;

    public string Name
    {
        get { return name; }
        set { name = value; }
    }

    public int Age
    {
        get { return age; }
        set { age = value; }
    }
}

9. What is inheritance in C#?

Inheritance is another core OOP concept, where a new class is created that inherits attributes and behaviors (fields and methods) from an existing class.

Here’s an example of inheritance in C#:

class Animal  // base class
{
    public void Eat()
    {
        Console.WriteLine("Eating");
    }
}

class Dog : Animal  // derived class
{
    public void Bark()
    {
        Console.WriteLine("Barking");
    }
}

10. What is an abstraction in C#?

Abstraction is the concept of hiding the complex reality while exposing only the necessary parts. In C#, abstraction is achieved using abstract classes and interfaces.

Here’s an example of abstraction in C#:

abstract class Animal  // abstract class
{
    public abstract void MakeSound();  // abstract method
}

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

11. What is an interface in C#?

An interface defines a contract for classes that implement it. It can contain properties, methods, and events, but they are all implicitly public and abstract.

Here’s an example of an interface in C#:

interface IAnimal  // interface
{
    void MakeSound();  // method
}

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

12. What is the difference between an interface and an abstract class in C#?

An interface is a contract that defines a set of methods that must be implemented by any class that implements the interface. An abstract class is a class that cannot be instantiated and may contain both abstract methods (methods with no implementation) and non-abstract methods (methods with implementation).

Here’s an example of how to use an interface and an abstract class in C#:

interface IDriveable
{
    void Drive();
}

abstract class Vehicle
{
    public abstract void StartEngine();
    public void StopEngine()
    {
        Console.WriteLine("Engine stopped");
    }
}

class Car : Vehicle, IDriveable
{
    public override void StartEngine()
    {
        Console.WriteLine("Engine started");
    }

    public void Drive()
    {
        Console.WriteLine("Car is driving");
    }
}

13. What is the difference between a delegate and an event in C#?

A delegate is a type that represents references to methods with a particular parameter list and return type. An event is a way for a class to provide notifications to its clients that something has happened.

Here’s an example of how to use a delegate and an event in C#:

class MyEventPublisher
{
    public delegate void MyEventHandler(string message);
    public event MyEventHandler MyEvent;

    public void RaiseEvent(string message)
    {
        if (MyEvent != null)
        {
            MyEvent(message);
        }
    }
}

class MyEventListener
{
    public void MyEventHandler(string message)
    {
        Console.WriteLine("Event raised: " + message);
    }
}

14. What is the difference between a field and a property in C#?

A field is a variable declared inside a class, while a property is a member of a class that provides access to fields through get and set accessors. Properties can have logic that validates the data being set or computed values based on other data in the class.

15. What is the difference between a static class and a non-static class in C#?

A static class is a class that cannot be instantiated, and all of its members are static. A non-static class, on the other hand, can be instantiated and may have both static and non-static members.

16. How does C# support multithreading?

C# supports multithreading through the System.Threading namespace. You can create a new thread by creating a new instance of the Thread class and passing a delegate that represents the method to be executed on the new thread.

17. What is the difference between a shallow copy and a deep copy in C#?

A shallow copy of an object is a new object that is a copy of the original object with a new reference. A deep copy of an object is a new object that is a copy of the original object along with copies of all the objects referenced by the original object.

18. What is the difference between “ref” and “out” keywords in C#?

The “ref” keyword is used to pass a variable by reference, which means that any changes made to the variable inside the method will be reflected outside the method. The “out” keyword is similar, but it does not require the variable to be initialized before it is passed to the method.

Here’s an example of how to use the “ref” and “out” keywords in C#:

class Program
{
    static void Main()
    {
        int x = 5;
        ChangeValue(ref x);
        Console.WriteLine(x); // Output: 10

        int y;
        InitializeValue(out y);
        Console.WriteLine(y); // Output: 5
    }

    static void ChangeValue(ref int a)
    {
        a = 10;
    }

    static void InitializeValue(out int b)
    {
        b = 5;
    }
}

19. What is the difference between a “continue” statement and a “break” statement in a loop in C#?

The “continue” statement skips the remaining code inside the loop and goes to the next iteration, while the “break” statement exits the loop.

Here’s an example of how to use the “continue” and “break” statements in C#:

class Program
{
    static void Main()
    {
        for (int i = 0; i < 5; i++)
        {
            if (i == 2)
                continue;

            if (i == 4)
                break;

            Console.WriteLine(i);
        }
    }
}

20. What is the difference between “is” and “as” operators in C#?

The “is” operator is used to check if an object is of a certain type, while the “as” operator is used to perform a safe cast. If the cast is not possible, the “as” operator returns null.

Here’s an example of how to use the “is” and “as” operators in C#:

class Program
{
    static void Main()
    {
        object obj = "Hello, world!";
        if (obj is string)
        {
            string str = obj as string;
            Console.WriteLine(str);
        }
    }
}

21. What is the “var” keyword in C#?

The “var” keyword is used for implicitly typed local variables. The compiler determines the type of the variable based on the value assigned to it.

Here’s an example of how to use the “var” keyword in C#:

class Program
{
    static void Main()
    {
        var x = 5; // int
        var y = "Hello, world!"; // string
        var z = 3.14; // double
    }
}

22. What is the “dynamic” keyword in C#?

The “dynamic” keyword is used for dynamic typing. It allows you to create variables whose type is determined at runtime.

Here’s an example of how to use the “dynamic” keyword in C#:

class Program
{
    static void Main()
    {
        dynamic x = 5;
        Console.WriteLine(x); // Output: 5

        x = "Hello, world!";
        Console.WriteLine(x); // Output: Hello, world!
    }
}

23. Explain the use of “yield” keyword in C#.

The “yield” keyword is used in an iterator block to provide a value to the enumerator object or to signal the end of the iteration.

Here’s an example of how to use “yield” in C#:

class Program
{
    static void Main()
    {
        foreach (var number in GetNumbers())
        {
            Console.WriteLine(number);
        }
    }

    static IEnumerable<int> GetNumbers()
    {
        yield return 1;
        yield return 2;
        yield return 3;
    }
}

24. What are extension methods in C#?

Extension methods are a way to add new methods to existing types without modifying the original type.

Here’s an example of how to create and use extension methods in C#:

class Program
{
    static void Main()
    {
        string s = "Hello, world!";
        Console.WriteLine(s.CountWords()); // Output: 2
    }
}

static class StringExtensions
{
    public static int CountWords(this string s)
    {
        return s.Split(' ').Length;
    }
}

25. What is the purpose of “using” statement in C#?

The “using” statement is used to ensure that an object that implements IDisposable is disposed of properly.

Here’s an example of how to use the “using” statement in C#:

class Program
{
    static void Main()
    {
        using (StreamWriter writer = new StreamWriter("file.txt"))
        {
            writer.WriteLine("Hello, world!");
        }
    }
}

26. What is the difference between “checked” and “unchecked” in C#?

The “checked” keyword is used to explicitly enable overflow checking for integral-type arithmetic operations and conversions, while the “unchecked” keyword is used to suppress overflow checking.

Here’s an example of how to use “checked” and “unchecked” in C#:

class Program
{
    static void Main()
    {
        int x = int.MaxValue;

        // Checked block
        try
        {
            checked
            {
                x++;
            }
        }
        catch (OverflowException)
        {
            Console.WriteLine("Overflow");
        }

        // Unchecked block
        unchecked
        {
            x++;
        }

        Console.WriteLine(x); // Output: -2147483648
    }
}

27. What is the purpose of “partial” keyword in C#?

The “partial” keyword allows you to split the definition of a class, struct, or interface across multiple files.

Here’s an example of how to use the “partial” keyword in C#:

// File1.cs
partial class MyClass
{
    public void Method1()
    {
        Console.WriteLine("Method1");
    }
}

// File2.cs
partial class MyClass
{
    public void Method2()
    {
        Console.WriteLine("Method2");
    }
}

// Program.cs
class Program
{
    static void Main()
    {
        MyClass obj = new MyClass();
        obj.Method1(); // Output: Method1
        obj.Method2(); // Output: Method2
    }
}

28. What is the difference between “public” and “internal” access modifiers in C#?

The “public” access modifier makes a member accessible from any code in the assembly or another assembly that references it, while the “internal” access modifier makes a member accessible only within its own assembly.

Here’s an example of how to use “public” and “internal” access modifiers in C#:

// Assembly1.cs
public class MyClass
{
    public int MyPublicProperty { get; set; }
    internal int MyInternalProperty { get; set; }
}

// Assembly2.cs
class Program
{
    static void Main()
    {
        MyClass obj = new MyClass();
        obj.MyPublicProperty = 5;
        obj.MyInternalProperty = 5;  // Error: 'MyClass.MyInternalProperty' is inaccessible due to its protection level
    }
}

29. What is the “readonly” keyword in C#?

The “readonly” keyword in C# is used to declare a field that can only be assigned a value during its declaration or within the constructor of the class in which it is defined.

Here’s an example of how to use “readonly” in C#:

class MyClass
{
    public readonly int MyProperty;

    public MyClass(int value)
    {
        MyProperty = value;
    }
}

class Program
{
    static void Main()
    {
        MyClass obj = new MyClass(5);
        Console.WriteLine(obj.MyProperty);  // Output: 5

        obj.MyProperty = 10;  // Error: 'MyClass.MyProperty' is readonly and cannot be assigned to
    }
}

30. What is the difference between “const” and “readonly” in C#?

“const” and “readonly” are both used to declare immutable values, but there are some differences between the two. “const” is used for compile-time constants, while “readonly” is used for runtime constants. “const” can only be used for primitive and built-in types, while “readonly” can be used for any type.

Here’s an example of how to use “const” and “readonly” in C#:

class MyClass
{
    public const int MyConst = 5;
    public readonly int MyReadOnly;

    public MyClass(int value)
    {
        MyReadOnly = value;
    }
}

class Program
{
    static void Main()
    {
        MyClass obj = new MyClass(10);
        Console.WriteLine(MyClass.MyConst);  // Output: 5
        Console.WriteLine(obj.MyReadOnly);   // Output: 10
    }
}

31. What is the “volatile” keyword in C#?

The “volatile” keyword in C# indicates that a field may be accessed by multiple threads concurrently and ensures that the most up-to-date value is used.

Here’s an example of how to use “volatile” in C#:

class Program
{
    private volatile bool stop;

    static void Main()
    {
        Program p = new Program();
        Thread t = new Thread(p.Run);
        t.Start();

        Thread.Sleep(1000);
        p.Stop();
    }

    void Run()
    {
        while (!stop)
        {
            // Do work
        }

        Console.WriteLine("Stopped");
    }

    void Stop()
    {
        stop = true;
    }
}

32. Explain the difference between “virtual” and “override” keywords in C#.

The “virtual” keyword in C# is used to declare a method, property, indexer, or event that can be overridden in derived classes. The “override” keyword is used to extend or modify a virtual/abstract method, property, indexer, or event of the base class.

Here’s an example of how to use “virtual” and “override” in C#:

class MyBaseClass
{
    public virtual void MyMethod()
    {
        Console.WriteLine("MyBaseClass.MyMethod");
    }
}

class MyDerivedClass : MyBaseClass
{
    public override void MyMethod()
    {
        Console.WriteLine("MyDerivedClass.MyMethod");
    }
}

class Program
{
    static void Main()
    {
        MyBaseClass obj1 = new MyBaseClass();
        obj1.MyMethod();  // Output: MyBaseClass.MyMethod

        MyBaseClass obj2 = new MyDerivedClass();
        obj2.MyMethod();  // Output: MyDerivedClass.MyMethod
    }
}

33. What is the “sealed” keyword in C#?

The “sealed” keyword in C# is used to prevent a class from being inherited by other classes.

Here’s an example of how to use “sealed” in C#:

sealed class MySealedClass
{
    public int MyProperty { get; set; }
}

class MyClass : MySealedClass  // Error: 'MyClass': cannot derive from sealed type 'MySealedClass'
{
}

34. What is the purpose of “try-catch” block in C#?

The “try-catch” block in C# is used to handle exceptions. The code inside the “try” block is executed, and if an exception occurs, the control is passed to the “catch” block.

Here’s an example of how to use “try-catch” in C#:

class Program
{
    static void Main()
    {
        try
        {
            int x = 0;
            int y = 5 / x;
        }
        catch (DivideByZeroException)
        {
            Console.WriteLine("Cannot divide by zero");
        }
    }
}

35. What is the purpose of “finally” block in C#?

The “finally” block in C# is used to execute code that should run regardless of whether an exception occurred or not.

Here’s an example of how to use “finally” in C#:

class Program
{
    static void Main()
    {
        try
        {
            int x = 0;
            int y = 5 / x;
        }
        catch (DivideByZeroException)
        {
            Console.WriteLine("Cannot divide by zero");
        }
        finally
        {
            Console.WriteLine("Finally block executed");
        }
    }
}

36. Explain the purpose of “as” and “is” operators in C#.

The “as” operator in C# is used to perform a safe cast. If the cast is not possible, it returns null instead of throwing an exception. The “is” operator is used to check if an object is of a certain type.

Here’s an example of how to use “as” and “is” in C#:

class Program
{
    static void Main()
    {
        object obj = "Hello, world!";
        string str = obj as string;
        if (str != null)
        {
            Console.WriteLine(str);  // Output: Hello, world!
        }

        if (obj is string)
        {
            Console.WriteLine("obj is a string");
        }
    }
}

37. What is “string interpolation” in C#?

String interpolation in C# is a way to format strings by including variables and expressions inside curly braces within a string literal. The variables and expressions are replaced by their values when the string is evaluated.

Here’s an example of how to use string interpolation in C#:

class Program
{
    static void Main()
    {
        string name = "John";
        int age = 30;
        Console.WriteLine($"My name is {name} and I am {age} years old.");  // Output: My name is John and I am 30 years old.
    }
}

38. What is the purpose of “nameof” operator in C#?

The “nameof” operator in C# returns the name of a variable, type, or member as a string. It is useful for reducing the risk of runtime errors due to misspelled names.

Here’s an example of how to use the “nameof” operator in C#:

class Program
{
    static void Main()
    {
        string name = "John";
        Console.WriteLine(nameof(name));  // Output: name
    }
}

39. What is the “null conditional” operator in C#?

The “null conditional” operator (also known as the “null propagation” operator) in C# is used to conditionally access members and elements of an object when it is not null.

Here’s an example of how to use the “null conditional” operator in C#:

class Program
{
    static void Main()
    {
        string str = null;
        int? length = str?.Length;
        Console.WriteLine(length);  // Output: null
    }
}

40. What is “tuple” in C#?

A tuple in C# is a data structure that holds a sequence of elements of different types. Tuples are useful when you want to return multiple values from a method.

Here’s an example of how to use tuples in C#:

class Program
{
    static void Main()
    {
        (string, int) tuple = ("John", 30);
        Console.WriteLine($"{tuple.Item1}, {tuple.Item2}");  // Output: John, 30
    }
}

41. What is LINQ in C#?

LINQ (Language Integrated Query) in C# is a set of features that introduces query capabilities directly into the C# language. With LINQ, you can query collections of objects, databases, XML, and more, using a SQL-like syntax.

Here’s an example of how to use LINQ in C#:

using System;
using System.Collections.Generic;
using System.Linq;

class Program
{
    static void Main()
    {
        List<int> numbers = new List<int> { 1, 2, 3, 4, 5 };
        IEnumerable<int> evenNumbers = from n in numbers
                                       where n % 2 == 0
                                       select n;
        foreach (int n in evenNumbers)
        {
            Console.WriteLine(n);  // Output: 2, 4
        }
    }
}

42. What is the difference between “IEnumerable” and “IQueryable” in LINQ?

“IEnumerable” and “IQueryable” are two interfaces in LINQ that represent a collection of data that can be queried. “IEnumerable” is used for in-memory collections, while “IQueryable” is used for remote data sources such as a database.

Here’s an example of how to use “IEnumerable” and “IQueryable” in C#:

using System;
using System.Collections.Generic;
using System.Linq;

class Program
{
    static void Main()
    {
        List<int> numbers = new List<int> { 1, 2, 3, 4, 5 };
        IEnumerable<int> evenNumbers = from n in numbers
                                       where n % 2 == 0
                                       select n;
        foreach (int n in evenNumbers)
        {
            Console.WriteLine(n);  // Output: 2, 4
        }

        IQueryable<int> oddNumbers = numbers.AsQueryable()
                                             .Where(n => n % 2 == 1);
        foreach (int n in oddNumbers)
        {
            Console.WriteLine(n);  // Output: 1, 3, 5
        }
    }
}

43. What is the difference between “async” and “await” in C#?

“async” and “await” are two keywords in C# that are used to write asynchronous code. The “async” keyword is used to declare a method that contains an “await” expression. The “await” keyword is used to wait for an asynchronous operation to complete.

Here’s an example of how to use “async” and “await” in C#:

using System;
using System.Threading.Tasks;

class Program
{
    static async Task Main()
    {
        await MyAsyncMethod();
    }

    static async Task MyAsyncMethod()
    {
        Console.WriteLine("Before");
        await Task.Delay(1000);
        Console.WriteLine("After");
    }
}

44. What is the difference between “Task” and “Task<T>” in C#?

“Task” and “Task<T>” are two classes in C# that represent asynchronous operations. “Task” represents a void asynchronous operation, while “Task<T>” represents an asynchronous operation that returns a value of type “T”.

Here’s an example of how to use “Task” and “Task<T>” in C#:

using System;
using System.Threading.Tasks;

class Program
{
    static async Task Main()
    {
        await MyAsyncMethod();
        int result = await MyAsyncMethodWithReturn();
        Console.WriteLine(result);  // Output: 42
    }

    static async Task MyAsyncMethod()
    {
        await Task.Delay(1000);
        Console.WriteLine("MyAsyncMethod completed");
    }

    static async Task<int> MyAsyncMethodWithReturn()
    {
        await Task.Delay(1000);
        return 42;
    }
}

45. What is the difference between “throw” and “throw ex” in C#?

“throw” and “throw ex” are two ways to re-throw exceptions in C#. “throw” re-throws the original exception, preserving its stack trace, while “throw ex” throws a new exception, losing the original stack trace.

Here’s an example of how to use “throw” and “throw ex” in C#:

using System;

class Program
{
    static void Main()
    {
        try
        {
            ThrowException();
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.StackTrace);  // Output: Original stack trace
        }
    }

    static void ThrowException()
    {
        try
        {
            throw new Exception("An error occurred");
        }
        catch (Exception ex)
        {
            //throw;           // Preserves original stack trace
            throw ex;        // Loses original stack trace
        }
    }
}

46. What is the garbage collector in C#?

The garbage collector (GC) in C# is a part of the .NET runtime that manages the allocation and deallocation of memory. It automatically reclaims memory that is no longer in use by the program, freeing up resources and preventing memory leaks.

47. How does the garbage collector work in C#?

The garbage collector works by periodically checking for objects in memory that are no longer reachable from the root of the application. These objects are considered garbage and are marked for collection. The garbage collector then reclaims the memory used by these objects, compacting the heap and making room for new objects.

Here’s an example of how the garbage collector works in C#:

using System;

class Program
{
    static void Main()
    {
        CreateObjects();
        Console.WriteLine("Objects created");

        GC.Collect();
        Console.WriteLine("Garbage collected");

        Console.ReadLine();
    }

    static void CreateObjects()
    {
        for (int i = 0; i < 1000; i++)
        {
            new object();
        }
    }
}

48. What are generations in the garbage collector in C#?

Generations are a concept used by the garbage collector to optimize memory management. There are three generations in the garbage collector: Generation 0, Generation 1, and Generation 2. Generation 0 is for short-lived objects, Generation 1 is for medium-lived objects, and Generation 2 is for long-lived objects. The garbage collector first collects objects in Generation 0, then Generation 1, and finally Generation 2.

Here’s an example of how generations work in C#:

using System;

class Program
{
    static void Main()
    {
        CreateObjects();
        Console.WriteLine("Objects created");

        GC.Collect(0);
        Console.WriteLine("Generation 0 collected");

        GC.Collect(1);
        Console.WriteLine("Generation 1 collected");

        GC.Collect(2);
        Console.WriteLine("Generation 2 collected");

        Console.ReadLine();
    }

    static void CreateObjects()
    {
        for (int i = 0; i < 1000; i++)
        {
            new object();
        }
    }
}

49. What is the “Dispose” method in C#?

The “Dispose” method in C# is used to release unmanaged resources such as file handles, database connections, and more. It is part of the IDisposable interface, which is implemented by classes that need to provide a way to clean up resources.

Here’s an example of how to use the “Dispose” method in C#:

using System;

class MyResource : IDisposable
{
    public void Dispose()
    {
        Console.WriteLine("Resource disposed");
    }
}

class Program
{
    static void Main()
    {
        using (MyResource resource = new MyResource())
        {
            // Use resource
        }  // Dispose is called automatically

        Console.ReadLine();
    }
}

50. What is the “finalizer” in C#?

The finalizer in C# is a special method that is called by the garbage collector when an object is collected. It is used to release unmanaged resources that are not released by the “Dispose” method. The finalizer is defined by overriding the “Finalize” method of the “Object” class.

Here’s an example of how to use the finalizer in C#:

using System;

class MyResource
{
    ~MyResource()
    {
        Console.WriteLine("Resource finalized");
    }
}

class Program
{
    static void Main()
    {
        new MyResource();
        GC.Collect();  // Finalize is called

        Console.ReadLine();
    }
}

51. What is “record” in C# 9.0?

A “record” in C# 9.0 is a reference type that provides built-in functionality for value-based equality, immutability, and other useful features for modeling data.

Here’s an example of how to use “record” in C#:

record Person(string FirstName, string LastName);

class Program
{
    static void Main()
    {
        Person person1 = new Person("John", "Doe");
        Person person2 = new Person("John", "Doe");
        Console.WriteLine(person1 == person2);  // Output: True
    }
}

52. What is “pattern matching” in C# 9.0?

Pattern matching in C# 9.0 is a feature that allows you to match expressions against patterns and perform actions based on whether the pattern matches or not.

Here’s an example of how to use pattern matching in C#:

class Program
{
    static void Main()
    {
        object obj = 42;
        if (obj is int i)
        {
            Console.WriteLine(i);  // Output: 42
        }
    }
}

53. What is “nullable reference types” in C# 8.0?

Nullable reference types in C# 8.0 is a feature that allows you to specify whether a reference type can be null or not.

Here’s an example of how to use nullable reference types in C#:

#nullable enable

class Program
{
    static void Main()
    {
        string str1 = "Hello";
        string? str2 = null;
        Console.WriteLine(str1.Length);  // Output: 5
        Console.WriteLine(str2?.Length);  // Output: null
    }
}

54. What is “default interface methods” in C# 8.0?

Default interface methods in C# 8.0 is a feature that allows you to provide a default implementation for a method in an interface.

Here’s an example of how to use default interface methods in C#:

interface IMyInterface
{
    void MyMethod() => Console.WriteLine("Default implementation");
}

class MyClass : IMyInterface
{
}

class Program
{
    static void Main()
    {
        MyClass obj = new MyClass();
        obj.MyMethod();  // Output: Default implementation
    }
}

55. What is “top-level statements” in C# 9.0?

Top-level statements in C# 9.0 is a feature that allows you to write programs without the need for a “Main” method or a “Program” class.

Here’s an example of how to use top-level statements in C#:

Console.WriteLine("Hello, world!");  // Output: Hello, world!

56. What is “init-only properties” in C# 9.0?

Init-only properties in C# 9.0 allow you to create immutable properties that can only be set during object initialization.

Here’s an example of how to use init-only properties in C#:

class Person
{
    public string FirstName { get; init; }
    public string LastName { get; init; }
}

class Program
{
    static void Main()
    {
        Person person = new Person { FirstName = "John", LastName = "Doe" };
        // person.FirstName = "Jane";  // Error: FirstName is init-only
        Console.WriteLine($"{person.FirstName} {person.LastName}");  // Output: John Doe
    }
}

57. What is “positional records” in C# 9.0?

Positional records in C# 9.0 allow you to create records with positional parameters, providing a concise way to declare properties and their corresponding constructor.

Here’s an example of how to use positional records in C#:

record Person(string FirstName, string LastName);

class Program
{
    static void Main()
    {
        Person person = new("John", "Doe");
        Console.WriteLine($"{person.FirstName} {person.LastName}");  // Output: John Doe
    }
}

58. What is “with-expressions” in C# 9.0?

With-expressions in C# 9.0 allow you to create a new instance of a record while keeping some of the property values from an existing instance.

Here’s an example of how to use with-expressions in C#:

record Person(string FirstName, string LastName);

class Program
{
    static void Main()
    {
        Person person1 = new("John", "Doe");
        Person person2 = person1 with { FirstName = "Jane" };
        Console.WriteLine($"{person1.FirstName} {person1.LastName}");  // Output: John Doe
        Console.WriteLine($"{person2.FirstName} {person2.LastName}");  // Output: Jane Doe
    }
}

59. What is “range and index” in C# 8.0?

Range and index in C# 8.0 provide a more concise way to access elements in arrays and collections.

Here’s an example of how to use range and index in C#:

class Program
{
    static void Main()
    {
        int[] numbers = { 1, 2, 3, 4, 5 };
        int last = numbers[^1];  // Output: 5
        int[] range = numbers[1..4];  // Output: 2, 3, 4
        Console.WriteLine(last);
        Console.WriteLine(string.Join(", ", range));
    }
}

60. What is “static anonymous functions” in C# 9.0?

Static anonymous functions in C# 9.0 allow you to declare anonymous functions without capturing any local variables or instance state.

Here’s an example of how to use static anonymous functions in C#:

class Program
{
    static void Main()
    {
        Func<int, int> square = static x => x * x;
        Console.WriteLine(square(5));  // Output: 25
    }
}

61. What are boxing and unboxing in C#?

Boxing and unboxing are mechanisms in C# for converting between value types and reference types. Boxing is the process of converting a value type to the type object or to any interface type implemented by this value type. Unboxing extracts the value type from the object. Boxing is implicit; unboxing is explicit.

Here’s an example of boxing and unboxing in C#:

int val = 23;    // Value type
object obj = val; // Boxing: int is converted to object

int valAgain = (int)obj; // Unboxing: object is converted back to int

When val is boxed to obj, a new object on the heap is created that contains the value of val. When obj is unboxed to valAgain, the value contained within obj is copied back into a value type, which is stored on the stack.

62. What are generics in C#?

Generics in C# allow you to define a class or method with a placeholder for the type of data it can store or use. The primary benefit of generics is to enable type safety and performance by allowing types to be specified at compile-time, avoiding the overhead of boxing/unboxing, and reducing the need for type casting.

Here is an example of a generic class in C#:

public class GenericList<T>
{
    private class Node
    {
        public Node Next;
        public T Data;
    }

    private Node head;

    public void AddHead(T t)
    {
        Node n = new Node() { Data = t, Next = head };
        head = n;
    }

    public IEnumerator<T> GetEnumerator()
    {
        Node current = head;
        while (current != null)
        {
            yield return current.Data;
            current = current.Next;
        }
    }
}

// Usage
var list = new GenericList<int>();
list.AddHead(1);
list.AddHead(2);
list.AddHead(3);
// list is now a type-safe list of integers

In this example, GenericList is a generic class that can store any type <T>. When you create an instance of GenericList <int>, it becomes a type-safe list specifically for integers. This way, you don’t have to use a non-generic collection like ArrayList, which stores objects and could cause run-time errors if the wrong type is accessed.

63. What is Dependency Injection in C#?

Dependency Injection (DI) in C# is a design pattern used to achieve Inversion of Control (IoC) between classes and their dependencies. It allows for decoupling the creation of a class’s dependencies from its behavior, making it easier to manage dependencies, test classes in isolation, and maintain code.

Here’s an example of how DI can be implemented in C#:

public interface ILogger
{
    void Log(string message);
}

public class ConsoleLogger : ILogger
{
    public void Log(string message)
    {
        Console.WriteLine(message);
    }
}

public class FileLogger : ILogger
{
    public void Log(string message)
    {
        // Code to log data to a file
    }
}

public class Application
{
    private readonly ILogger _logger;

    // Constructor injection
    public Application(ILogger logger)
    {
        _logger = logger;
    }

    public void Run()
    {
        _logger.Log("Application is running.");
        // Application code goes here
    }
}

// Usage
class Program
{
    static void Main(string[] args)
    {
        ILogger logger = new ConsoleLogger();
        Application app = new Application(logger);
        app.Run();
    }
}

In this code, Application class is dependent on the ILogger interface, not on a concrete implementation of ILogger. ConsoleLogger and FileLogger are concrete implementations that can be injected into Application. The Main method creates an instance of ConsoleLogger and injects it into Application when creating its instance. This means Application is not responsible for creating the logger it uses, which is the essence of DI.

64. What are partial classes in C#, and what are the advantages of using them?

Partial classes in C# allow a single class to be split into two or more files. This feature enables multiple programmers to work on the same class simultaneously without causing file conflicts in a version control system. It also helps in separating different concerns or functionalities of a class into different files for better maintainability.

Here’s an example of how partial classes might be used:

Employee.Data.cs

public partial class Employee
{
    public int Id { get; set; }
    public string Name { get; set; }
}

Employee.Logic.cs

public partial class Employee
{
    public void CalculatePay()
    {
        // Method implementation
    }
}

Both parts are combined into the same Employee class when the application is compiled.

Advantages of using partial classes:

  • Separation of Concerns: Different aspects of a class can be separated into different files (e.g., data model, business logic, and data access code).
  • Team Collaboration: Allows multiple developers to work on the same class in a collaborative environment without merge conflicts since they are working in separate files.
  • Manageability: For classes with a large amount of code, splitting the class into partial classes can improve readability and manageability.
  • Code Generation: Partial classes are particularly useful when working with automatically generated code. You can allow code generators to create one part of a class, while you manually code the other part without risk of the generated code overwriting your custom code.
  • Organization: Helps in organizing the code logically. For instance, you can have separate files for nested classes, enumerations, or interfaces related to the main class, making the structure of your project more intuitive.

65. Write a program to reverse an integer number in C# without using a built-in function.

Here is a simple C# program that demonstrates how to reverse an integer number without using any built-in function:

using System;

class Program
{
    static void Main()
    {
        int number, reverse = 0;
        Console.WriteLine("Enter a number:");
        number = int.Parse(Console.ReadLine());

        while (number != 0)
        {
            int remainder = number % 10;
            reverse = (reverse * 10) + remainder;
            number /= 10;
        }

        Console.WriteLine("Reversed Number: " + reverse);
    }
}

This program takes an integer as input and reverses it using arithmetic operations. It does so by repeatedly taking the last digit of number (using number % 10) and adding it to reverse, which is being built up by multiplying the current reverse by 10 and then adding the last digit. It then removes the last digit from number by dividing it by 10.

66. Write a program to check if a string is a palindrome

A palindrome is a string that reads the same backward as forward. Here’s how you might write a program in C# to check if a string is a palindrome:

using System;

class Program
{
    static void Main()
    {
        Console.WriteLine("Enter a string:");
        string input = Console.ReadLine();

        bool isPalindrome = true;
        int length = input.Length;

        for (int i = 0; i < length / 2; i++)
        {
            if (input[i] != input[length - i - 1])
            {
                isPalindrome = false;
                break;
            }
        }

        Console.WriteLine(isPalindrome ? "The string is a palindrome." : "The string is not a palindrome.");
    }
}

This program compares characters in the string from the beginning to the end, moving towards the center.

If any characters don’t match, it sets isPalindrome to false and breaks out of the loop.

67. Write a program to find the factorial of a number using loops.

The factorial of a number n (denoted as n!) is the product of all positive integers less than or equal to n.

Here’s a C# program to calculate factorial:

using System;

class Program
{
    static void Main()
    {
        Console.WriteLine("Enter a number:");
        int number = int.Parse(Console.ReadLine());
        long factorial = 1;

        for (int i = 1; i <= number; i++)
        {
            factorial *= i;
        }

        Console.WriteLine("Factorial of " + number + " is: " + factorial);
    }
}

This program initializes factorial to 1 and then iterates from 1 to the number entered, multiplying factorial by each integer.

68. Write a program in C# to find the sum of digits of a number

Here’s a C# program that calculates the sum of the digits of an integer:

using System;

class Program
{
    static void Main()
    {
        Console.WriteLine("Enter a number:");
        int number = int.Parse(Console.ReadLine());
        int sum = 0;

        while (number != 0)
        {
            sum += number % 10;
            number /= 10;
        }

        Console.WriteLine("Sum of the digits: " + sum);
    }
}

This program uses a loop to extract each digit of the number by taking the remainder when divided by 10 and then adds it to sum. The number is then divided by 10 to remove the last digit. This process continues until the number is reduced to 0.

69. Write a program in C# to check whether a number is prime or not.

A prime number is a natural number greater than 1 that has no positive divisors other than 1 and itself. Here’s a C# program to determine whether a given number is prime:

using System;

class Program
{
    static void Main()
    {
        Console.Write("Enter a number: ");
        int num = int.Parse(Console.ReadLine());
        bool isPrime = true;

        if (num <= 1) isPrime = false;
        else if (num > 2)
        {
            for (int i = 2; i <= Math.Sqrt(num); i++)
            {
                if (num % i == 0)
                {
                    isPrime = false;
                    break;
                }
            }
        }

        Console.WriteLine($"{num} is {(isPrime ? "" : "not ")}a prime number.");
    }
}

This program checks for divisibility starting from 2 up to the square root of the number. If any divisor is found, it flags the number as not prime.

70. Write a program in C# to print the Fibonacci series up to n terms

The Fibonacci sequence is a series of numbers where the next number is found by adding up the two numbers before it. Here’s how to print the Fibonacci sequence up to n terms in C#:

using System;

class Program
{
    static void Main()
    {
        Console.Write("Enter the number of terms: ");
        int terms = int.Parse(Console.ReadLine());

        int firstNumber = 0, secondNumber = 1, nextNumber = 0;

        Console.Write("Fibonacci Series: ");
        for (int i = 1; i <= terms; i++)
        {
            if (i == 1)
            {
                Console.Write($"{firstNumber} ");
                continue;
            }
            if (i == 2)
            {
                Console.Write($"{secondNumber} ");
                continue;
            }
            nextNumber = firstNumber + secondNumber;
            firstNumber = secondNumber;
            secondNumber = nextNumber;
            Console.Write($"{nextNumber} ");
        }
    }
}

This program uses iteration to generate each term, starting with the first two terms of the series: 0 and 1.

71. Write a program in C# to convert a binary number to its decimal equivalent

Binary numbers consist of only 0s and 1s. To convert a binary number to a decimal, we multiply each bit by 2 raised to the power of its position number, starting from 0. Here is the C# code:

using System;

class Program
{
    static void Main()
    {
        Console.Write("Enter a binary number: ");
        string binaryNumber = Console.ReadLine();
        int decimalValue = 0;

        for (int i = 0; i < binaryNumber.Length; i++)
        {
            if (binaryNumber[binaryNumber.Length - i - 1] == '1')
            {
                decimalValue += (int)Math.Pow(2, i);
            }
        }

        Console.WriteLine($"Decimal Value: {decimalValue}");
    }
}

In this program, the input is a string representing a binary number. It calculates the decimal value by iterating through each digit of the binary number from right to left and adding the value of 2 raised to the position of the digit (if it is ‘1’) to the result.

72. What is a Singleton Design Pattern in C#?

The Singleton design pattern is a software design principle that is used to ensure that a class has only one instance while providing a global point of access to that instance. It is used when only a single instance of a class is required to control the action throughout the execution. A common example might be a database connection pool or a file manager.

The key features of a Singleton pattern are:

  • A single constructor, that is private and parameterless.
  • The class is sealed to prevent inheritance and hence, no subclass can make a singleton class non-singleton.
  • A static variable that holds a reference to the single created instance, if any.
  • A public static means of getting the reference to the single created instance, creating one if necessary.

Here’s an example of how to implement a Singleton in C#:

public sealed class Singleton
{
    private static Singleton _instance = null;
    private static readonly object _lock = new object();

    // Private constructor ensures that an object is not instantiated from outside the class.
    private Singleton() {}

    public static Singleton Instance
    {
        get
        {
            // Support multithreaded applications through 'Double checked locking' pattern which 
            // (once the instance exists) avoids locking each time the method is invoked
            if (_instance == null)
            {
                lock (_lock)
                {
                    if (_instance == null)
                    {
                        _instance = new Singleton();
                    }
                }
            }
            return _instance;
        }
    }
}

In this example, _instance is a static variable that holds the instance of the Singleton class. The Instance property checks whether an instance has been created; if not, it creates one in a thread-safe manner. This thread safety is achieved by locking on the _lock object.

73. What is Interface Inheritance in C#?

In C#, interfaces can inherit from other interfaces. This is known as interface inheritance and allows the creation of a new interface that combines the members of one or more existing interfaces.

Interface inheritance promotes reusability and enables polymorphic behavior. When a class implements an interface that inherits other interfaces, it must provide implementations for all members declared within the interface hierarchy.

Here’s an overview of how interface inheritance works in C#:

  • An interface can inherit from one or more other interfaces.
  • A class that implements the inherited interface must implement all members of the interface chain.
  • Unlike class inheritance, interface inheritance does not define any implementation details—it only defines the signatures of functionality that implementing classes must provide.
  • Interfaces support multiple inheritances, so a single interface can inherit members from multiple other interfaces.

Let’s look at a simple example of interface inheritance:

// Base interface with a method signature
public interface IVehicle
{
    void StartEngine();
}

// Derived interface inheriting from IVehicle
public interface ICar : IVehicle
{
    void OpenTrunk();
}

// Implementing the derived interface requires implementation of both IVehicle and ICar members
public class Sedan : ICar
{
    public void StartEngine()
    {
        Console.WriteLine("Engine started.");
    }

    public void OpenTrunk()
    {
        Console.WriteLine("Trunk opened.");
    }
}

In this example, ICar inherits from IVehicle. The Sedan class implements ICar, and as a result, it is required to implement both StartEngine from IVehicle and OpenTrunk from ICar.

74. What is Reflection in C#?

Reflection in C# is a powerful feature that allows you to inspect the metadata of types at runtime, create instances of types, invoke methods, and access fields and properties regardless of the access modifiers (like private or protected). This can be especially useful for tasks such as browsing and querying attributes, or for creating type browsers and debuggers, where you need to work with types that are not known until runtime.

Reflection is provided by the System.Reflection namespace. It includes classes such as Type, MethodInfo, PropertyInfo, EventInfo, FieldInfo, and Assembly, among others, which can be used to explore the structure of code.

Here’s an example of using reflection to get information about a class and to invoke its method:

using System;
using System.Reflection;

public class Vehicle
{
    private string brand;

    public Vehicle(string brand)
    {
        this.brand = brand;
    }

    public void Display()
    {
        Console.WriteLine($"This vehicle is a {brand}.");
    }
}

class ReflectionDemo
{
    static void Main()
    {
        Type type = typeof(Vehicle);

        // Get the constructor and create an instance
        ConstructorInfo constructor = type.GetConstructor(new[] { typeof(string) });
        object vehicleInstance = constructor.Invoke(new object[] { "Toyota" });

        // Get the Display method and invoke it
        MethodInfo displayMethod = type.GetMethod("Display");
        displayMethod.Invoke(vehicleInstance, null);
    }
}

In this code, reflection is used to inspect the Vehicle class, instantiate it with a parameter, and invoke its Display method.

75. What will be the salary expectations for an experienced C# developer?

As an experienced C# developer in the United States, your salary expectations should align with the current market rates, which vary depending on several factors, including your level of experience, the industry, location, and the size of the company you’re looking to join.

Here is an overview:

Experience LevelAverage Base Salary (annually)Potential Additional Compensation (bonuses, profit sharing, etc.)
3-5 years (Mid-level)$75,000 – $100,000$2,000 – $10,000
5-10 years (Senior)$95,000 – $120,000$5,000 – $15,000
10+ years (Lead/Expert)$110,000 – $150,000+$10,000 – $30,000+

Please note: These figures are estimates and subject to change. The actual salaries can vary significantly.

Factors Affecting Salary for a C# senior developer:

  1. Location: Salaries in major tech hubs like San Francisco, New York, or Seattle are typically higher than the national average due to the high cost of living and competitive tech markets.
  2. Industry: Certain industries like finance, healthcare, and technology might offer higher salaries compared to others due to the demand and the critical nature of the software being developed.
  3. Company Size: Large companies often have the resources to offer higher salaries and more comprehensive benefits packages. Startups may offer less in terms of salary but might compensate with equity or other incentives.
  4. Skill Set and Specializations: In addition to proficiency in C#, skills in .NET Core, ASP.NET, cloud services (Azure, AWS), and knowledge of front-end technologies can increase your value.
C# Interview Questions and Answers for Experienced Professionals

Conclusion

C# is a powerful programming language that is widely used in the industry. You will see a lot of job openings available in the IT industry. So, it is important for experienced professionals to have a strong understanding of C# concepts and features, as well as the ability to apply them in real-world scenarios.

The C# interview questions and answers for experienced professionals provided in this post cover a range of topics, including basic and advanced concepts, as well as the latest features introduced in C# 9.0 and C# 8.0. I hope that these questions and answers will help you prepare for your C# interview and increase your chances in getting a job as a senior C#.Net developer.

You may also like: