Home » Interview Questions Answers » 100+ C# Interview Questions & Answers

100+ C# Interview Questions & Answers


csharp-C#-interview-questions-answers

C# (pronounced “C-sharp”) is a modern, object-oriented programming language developed by Microsoft. It is part of the .NET framework and is used to build a variety of applications, including web, desktop, mobile, and cloud-based applications. C# is known for its strong type-safety, garbage collection, and features that support software development. It is widely used in enterprise environments and is one of the primary languages for developing applications on the Microsoft platform. Read more – C# Version History and features. Here, we will provide 100+ C# Interview Questions and Answers which are suitable for both freshers and experienced professionals with 2, 5, and 10 years of experience.


C# Interview Questions & Answers

Download all Questions as .PDF




How do you call a base class constructor from a derived class?

You can call a base class constructor from a derived class using the base keyword followed by the parameters required by the base class constructor. This is typically done in the derived class’s constructor.





Usage of Destructor in C#

In C#, the garbage collector manages memory automatically, so destructors are not often needed for basic memory management tasks. Instead, the IDisposable interface and the using statement are preferred for deterministic disposal of resources. It should be used only when necessary because it can add overhead to the garbage collection process.

When to Use Destructors:

  • Unmanaged Resources: When your class uses unmanaged resources such as file handles, network connections, or database connections.
  • Resource Management: When you need to ensure that resources are released when the object is no longer needed.
  • Finalization Logic: When you need to perform specific finalization logic before an object is destroyed.




What are Static members in a class?

Static members in a class are members that belong to the class itself rather than to any specific instance of the class. This means that static members are shared among all instances of the class, and they can be accessed without creating an instance of the class.

Static members are typically stored in a separate area of memory reserved for the class, rather than in the heap where instance-specific data is stored.

Types of Static Members:

  • Static Fields: Variables that are shared among all instances of the class.
  • Static Methods: Functions that can be called on the class itself, rather than on instances of the class.
  • Static Properties: Properties that provide access to class-level data.
  • Static Constructors: Special constructors used to initialize static fields or perform actions that need to be done only once.




Does C# support multiple inheritance? (or) Can a class implement multiple interfaces in C#?

No, C# does not support multiple inheritance for classes to avoid complexities like the diamond problem, where it becomes unclear which parent class’s method should be called when methods with the same name exist in multiple parent classes. This means a class in C# cannot directly inherit from more than one base class. However, C# does support multiple inheritance through interfaces, which allows a class to implement multiple interfaces.




What is explicit Interface implementation?

Explicit interface implementation allows a class to implement interface members explicitly, providing a way to differentiate which interface’s method is being implemented when a class implements multiple interfaces that have members with the same signature. This helps avoid naming conflicts and ensures that interface methods are only accessible through an interface reference.





What is the work of a constructor?

A constructor creates and initializes the objects in an application.




Can we declare a constructor to private?

Yes




What is a constructor initializer in C#?

A constructor initializer in C# is a way to specify that a constructor should call another constructor in the same class (using this) or a constructor in the base class (using base) before executing the rest of the constructor’s body. This is useful for reusing constructor logic and ensuring that base class constructors are properly called.

Types of Constructor Initializers:

  1. ‘this’ Initializer is used to call another constructor in the same class. It helps to avoid code duplication by reusing constructor logic.
  2. ‘base’ Initializer is used to call a constructor in the base class. Ensures that the base class is properly initialized.




How to prevent a public class method to be overridden in drive class?

Make method sealed by using sealed keyword.




How to stop a class being inherited by another class?

Make the class sealed by using sealed keyword.




How to prevent a class being instantiated?

Make class abstract or static




Can you derive a static method of base class in child class?

No, you cannot derive a static method of a base class in a child class. In C#, static methods belong to the class itself rather than to any instance of the class. This means they are not inherited by derived classes in the same way that instance methods are.




Can you override a normal public method of base class and make it static?

No , the method signature should be same to be overridden.




How to override a private virtual method?

You cannot override a private method.




What is the difference between ‘override’ and ‘new’ keywords in C#?


override new
Extends or modifies a virtual/abstract method in a base class Hides a method, property, indexer, or event inherited from a base class
Requires the base method to be marked as virtual, abstract, or override Can hide any base class member, whether virtual or not
Supports runtime polymorphism Does not support runtime polymorphism
Method Call Determined by the object's runtime type Determined by the reference type
Base Class Method must exist in the base class as virtual, abstract, or override Can exist with any modifier in the base class
Keyword must be virtual, abstract, or override in the base class Can be any keyword in the base class



What is Early and Late Binding?

Early Binding: Methods or properties are determined at compile time, resulting in faster execution and early error detection.

Late Binding: Methods or properties are determined at run time, offering more flexibility but potentially slower execution and late error detection.




Early Binding Late Binding
Determination Time Compile Time Run Time
Performance Faster Slower
Type Safety Checked at compile time Checked at run time
Flexibility Less flexible More flexible
Error Detection Compile time (early detection) Run time (late detection)



Can namespace contain the private class?

No, having a single private class does not mean anything , it is applicable only in case of nested class.




Can we have Sealed Method in abstarct class ?

No, an abstract class cannot have a sealed method directly because abstract methods must be overridden in derived classes, and sealing is meant to prevent further overriding.

How to Work Around: ou can achieve a similar effect by providing a virtual method in the abstract class, then override and seal it in a derived class.





Why cannot I have abstract static methods in C#?

You cannot have abstract static methods because the concepts of “abstract” and “static” are fundamentally incompatible.
Abstract Methods: Require overriding in derived classes.
Static Methods: Cannot be overridden and belong to the class itself.

Implementation Requirement: Abstract methods are intended to be overridden and given concrete implementations in derived classes. However, static methods cannot be overridden.

Instance Context: Abstract methods operate within the context of an instance of a class, whereas static methods operate without any instance context.

The need for overriding (abstract) and the inability to be overridden (static) make it logically impossible to have a method that is both abstract and static.




Can we have Multiple Main Methods in one .cs file?

Yes




Can you declare the override method static while the original method is non-static?

No, you can’t, the signature of the virtual method must remain the same, only the keyword virtual is changed to keyword override.




Can you override private virtual methods?

No, you cannot access private methods in inherited classes.




Static methods cannot use Non-Static members. True or False?

True




If the Function has same parameter but different return type (int and float), Is it a overloading?

No, having a function with the same parameter list but different return types is not considered overloading in C#. Function overloading requires the parameter lists to differ in number, type, or order of parameters, not just the return type.





Overloading is Static Polymorphism and Overriding is Dynamic Polymorphism? True or False?

True




What are the default access modifiers for various elements in C#?


Element Type Default Access Modifier
Top-Level Class internal
Nested Class private
Struct internal
Interface internal
Enum public
Delegate internal
Class Member (Field, Method, Property, Event) private
Struct Member (Field, Method, Property, Event) private
Enum Member public
Interface Member (Method, Property, Event) public
Constructor private
Destructor private



Why is a const variable available within a static method?


const members are implicitly static. They belong to the class rather than a specific instance. Because they are static, const variables are accessible within static methods without needing an instance of the class.

A static method can only access other static members (fields, properties, methods) of the class. Since const variables are static, they can be accessed from within static methods.





How does C# handle Method Hiding?

Method hiding is done using the new keyword. Method hiding occurs when a derived class defines a method with the same name as a method in its base class. The new method hides the base class method. (continue reading the next Question to see a sample example for Hiding Members).




Use of “New” keyword in C#


The new keyword in C# has multiple uses.

1. Creating Objects: The new keyword is used to create instances of types (objects). This is the most common use.

// Creating an instance of MyClass
MyClass obj = new MyClass(); 

2) Hiding Members: The new keyword can be used to hide a member inherited from a base class. This is known as member hiding.



3) Creating Instances of Anonymous Types: The new keyword is also used to create instances of anonymous types.

var anonType = new { Name = "John", Age = 30 }; 

4) Creating Instances of Array: The new keyword is used to create instances of arrays.

int[] numbers = new int[5]; 

5) Creating Instances of Value Types: The new keyword can be used to create instances of value types.





Boxing and Unboxing in C#


Boxing: Converting a value type to a reference type

object obj = 123; 

Unboxing: Converting a reference type back to a value type

int num = (int)obj; 

Boxing and unboxing involve additional overhead due to heap allocation and type conversion, which can affect performance. Useful when you need to treat value types as objects, such as when storing them in non-generic collections.




What do you mean by ‘Mutable’ in C#

In C#, an object is considered mutable if its state or fields can be changed after it is created. Mutable objects allow modification of their data members.




Difference between String Vs StringBuilder


String StringBuilder
Immutability Immutable (cannot be changed after creation) Mutable (can be changed after creation)
Performance for Modifications Inefficient for frequent modifications (creates new instances) Efficient for frequent modifications (modifies in place)
Memory Usage Higher memory usage due to creation of new instances Lower memory usage due to in-place modifications
Use Case Suitable for operations with few or no modifications Suitable for operations with many modifications
Methods for Modification Methods like Replace, Concat, Substring Methods like Append, Insert, Remove, Replace
Namespace System System.Text
Thread Safety Thread-safe (due to immutability) Not thread-safe without external synchronization




Difference between ‘Const’ Vs ‘Read Only’


const readonly
Must be assigned at declaration Can be assigned at declaration or in a constructor
Immutable – Once assigned, cannot be changed. Immutable after initialization -Can be assigned once (at declaration or in a constructor) and then cannot be changed.
Compile-time constant Run-time constant
Static by default Can be instance-level or static
Limited to strings and primitive types Can be used with any type, including reference types
Initialized Only in the field declaration Initialized in the field declaration or in a constructor
Better performance due to inlining Slight overhead due to run-time evaluation
Requires the const keyword Requires the readonly keyword
Allocated once per program Allocated once per instance (if not static)




What is Virtual method?

A virtual method is a method in a base class that can be overridden by a derived class. This allows the derived class to provide a specific implementation of the method, which will be used instead of the base class implementation. The virtual keyword is used in the base class, and the override keyword is used in the derived class.





What is Collection in C#?

A Collection refers to a data structure that is used to store, manage, and manipulate groups of related objects. Collections provide various ways to store, access, and iterate over data, making them fundamental in programming for handling multiple items.

Types of Collections:

  1. Non-Generic Collections: These are collections that can store any type of object. They are part of the System.Collections namespace.
    Example: ArrayList, Hashtable, Queue, Stack, SortedList.
  2. Generic Collections: These collections provide type safety by allowing you to specify the type of elements stored in the collection. They are part of the System.Collections.Generic namespace.
    Example: List, Dictionary, Queue, Stack, SortedList, HashSet, LinkedList
  3. Concurrent Collections: These collections are designed for multi-threaded scenarios, providing thread-safe operations. They are part of the System.Collections.Concurrent namespace.
    Example: ConcurrentDictionary, ConcurrentQueue, ConcurrentStack, ConcurrentBag




How do you implement a custom collection class?

Implementing a custom collection class in C# involves creating a class that encapsulates a collection of items and provides methods for adding, removing, and manipulating these items. To integrate well with .NET, it’s often useful to implement standard collection interfaces like IEnumerable<T>, ICollection<T>, or IList<T>.





What is ArrayList? When to use?

An ArrayList is a non-generic collection in C# that can store elements of any type, including both value types and reference types. It is part of the System.Collections namespace. Unlike arrays, the size of an ArrayList can dynamically increase or decrease as elements are added or removed.

When to Use:

  • When Type Safety is Not a Concern: Use ArrayList when you do not need type safety and are working with a collection of objects of different types.
  • Legacy Code: ArrayList is useful when maintaining or working with legacy code that already uses this collection.
  • Quick Prototyping: For quick prototyping or small scripts where performance and type safety are not critical, ArrayList can be convenient.

Considerations:

  • Type Safety: ArrayList does not provide compile-time type checking. This can lead to runtime errors if incorrect types are added or accessed.
  • Performance: ArrayList can be less efficient than generic collections, such as List<T>, due to boxing and unboxing of value types and the lack of type safety.

Note: It is generally recommended to use generic collections, such as List<T>, which provide type safety and better performance.





What is List? When to use?

A List in C# is a generic collection that can store elements of a specific type, providing type safety & preventing runtime type errors, and providing dynamic resizing. It is part of the System.Collections.Generic namespace

When to Use:

  • Use List<T> when you need to ensure that all elements in the collection are of the same type, providing compile-time type checking and reducing runtime errors.
  • When you need efficient random access to elements, as well as efficient resizing and insertion/removal operations.




Difference between ArrayList and List.


ArrayList List<T>
Type Safety No (can store any type) Yes (stores elements of a specified type)
Performance Potential boxing/unboxing issues with value types No boxing/unboxing, better performance with value types
Generic No Yes
Initialization ArrayList arrayList = new ArrayList(); List<int> list = new List<int>();
Namespace System.Collections System.Collections.Generic
Usage Legacy code, non-type safe scenarios Modern C# development, type-safe scenarios



Difference between Array and List<T>.


Array List<T>
Fixed size, defined at initialization Dynamic size, can grow or shrink
Supports both reference and value types Generic, supports any type T
Faster for fixed-size operations Slightly slower due to resizing operations
Contiguous block of memory Allocates more memory as needed
Less flexible due to fixed size More flexible with dynamic resizing
Limited built-in methods (e.g., Length, CopyTo) Rich set of methods (e.g., Add, Remove, Find)
Simple, direct initialization Initialization Requires specifying type, more verbose
Direct element access via index Direct element access via index
Good for scenarios where size is constant and known Ideal for scenarios where size changes dynamically
Limited LINQ support Extensive support for LINQ queries

Array example:

int[] numbers = new int[5] { 1, 2, 3, 4, 5 };
// Fixed size, can't add or remove elements

List<T> example:

List<int> numbers = new List<int> { 1, 2, 3, 4, 5 };
numbers.Add(6); // Can add more elements dynamically



What is HashTable? When to use?

A Hashtable in C# is a collection that stores key-value pairs. It is part of the System.Collections namespace and allows for fast retrieval of values (Fast Lookups) based on their keys. The keys in a Hashtable must be unique, and each key is associated with exactly one value. Can store keys and values of any type, but does not provide type safety at compile time. Dynamically resizes to accommodate the number of elements.

When to Use:

  • When you need to store data as key-value pairs for quick retrieval based on the key.
  • When maintaining or working with legacy code that uses Hashtable.
  • When dealing with relatively small collections where the non-generic nature and potential boxing/unboxing overhead are not significant issues.

Note: It is generally recommended to use the generic Dictionary<TKey, TValue> collection, which provides type safety and better performance.





What is Dictionary? When to use?

A Dictionary in C# is a generic collection that stores key-value pairs. It is part of the System.Collections.Generic namespace and provides a fast way to look up values based on their keys. The keys in a Dictionary must be unique, and each key is associated with exactly one value.

When to Use: When you want to ensure that all keys and values are of specific types, providing compile-time type checking and need to store data as key-value pairs for quick retrieval based on the key.





Difference between HashTable and Dictionary.


Hashtable Dictionary<TKey, TValue>
Type Safety No (can store any type) Yes (stores elements of specified key and value types)
Performance Potential boxing/unboxing issues with value types No boxing/unboxing, better performance with value types
Generic No Yes
Initialization Hashtable hashtable = new Hashtable(); Dictionary<string, int> dictionary = new Dictionary<string, int>();
Namespace System.Collections System.Collections.Generic
Usage Legacy code, non-type safe scenarios Modern C# development, type-safe scenarios



How do you implement a ConcurrentDictionary in C#?

ConcurrentDictionary provides a thread-safe collection that allows multiple threads to concurrently add, update, or remove items from the dictionary without requiring manual synchronization, such as using locks.

ConcurrentDictionary<int, string> dictionary = new ConcurrentDictionary<int, string>();




What is Enum in C#?

An enum (short for “enumeration”) in C# is a value type that allows you to define a group of named constants. Enums are useful for representing a collection/group of related values, making your code more readable and maintainable by providing meaningful names to those values instead of using random numeric values.

The default type of enum is int. Enums are strongly typed, ensuring compile-time type safety. You cannot create an instance of an enum using the new keyword (Cannot Be Instantiated).

The members of an enum are accessed in a static-like manner, meaning you do not create an instance of the enum to access its values.

When to Use: When you need to define a group of related constants, such as days of the week, error codes, or status codes.





What are partial classes in C#?

Partial classes allow a class definition to be split across multiple files and each part must use the partial keyword. This can be particularly useful for organizing large classes or when working with auto-generated code, where you might want to separate the generated code from your custom code (Separation of Concerns).

All parts of the partial class must be defined in the same assembly and namespace.

All parts of the partial class are combined into a single class when the application is compiled.





What is a partial method in C#?

A partial method in C# is a method that is declared in one part of a partial class or struct and optionally implemented in another part. Partial methods enable developers to define method signatures within a class, allowing other parts of the class to provide the implementation or leave it empty. If the method is not implemented, the compiler removes its declaration and calls, resulting in no performance penalty.

Restrictions or Limitations:

  • Partial methods must return void.
  • They cannot have access modifiers; they are implicitly private.
  • They cannot be extern, virtual, abstract, override, or static.




Synchronous vs. Asynchronous Operations in C#

Synchronous operations are operations that run sequentially. Each operation must complete before the next one starts. The program execution waits for the current operation to finish before moving to the next operation.

Asynchronous operations allow a program to initiate an operation and then move on to other tasks without waiting for the operation to complete. The program can continue running other tasks, and the operation will complete at some point in the future.




Synchronous Asynchronous
Sequential, one operation at a time Concurrent, multiple operations can overlap
Blocks the calling thread Does not block the calling thread
Simpler to implement and understand More complex due to callbacks, continuations, etc.
Suitable for CPU-bound tasks Suitable for I/O-bound or long-running tasks
Can cause the application to become unresponsive Improves application responsiveness, especially for I/O-bound tasks



What are Serialization and Deserialization in C#?

Serialization is the process of converting an object into a format that can be easily stored or transmitted, such as JSON, XML, or binary.

Deserialization is the process of converting the serialized data back into an object.

In C#, serialization and deserialization are commonly used when working with data exchange, file storage, or communication between applications. The .NET framework provides built-in classes such as JsonSerializer, XmlSerializer, and BinaryFormatter for these purposes.




What are extension methods in C#?

Extension methods are a special kind of static method in C# that allows you to add new methods to existing types without modifying the original type or creating a new derived type. Defined as static methods in static classes and called as if they were instance methods. It Improves readability, reusability, and maintainability of code. It Cannot access private members.

The first parameter specifies which type the method operates on, and it is preceded by the this keyword.

Best Practices:

  • Use carefully: Don’t overuse extension methods. They should enhance readability and maintainability, not complicate the codebase.
  • Naming: 1) Choose method names that clearly convey their purpose and match the naming conventions of the extended type. 2) If multiple extension methods with the same name and signature are available, it can cause naming conflicts.
  • Namespaces: Place extension methods in appropriate namespaces and use using directives to include them only where needed.




What is the purpose of ‘using’ statement in C#?

The using statement ensures proper disposal of resources that implement IDisposable and when they are no longer needed, e.g., unmanaged resources like file handles, database connections, and network connections.





How do you use the ‘using’ directive to manage namespaces?

The using directive simplifies referencing types from namespaces. It allows you to avoid fully qualifying type names, manage scope, create aliases for namespaces or types, and import static members for direct access. It is typically placed at the top of a file.


  1. Simplify Code: Avoids writing fully qualified names.
  2. Aliases: Creates shortcuts for namespaces or types.
  3. Static Using: Imports static members for easier access.
  4. Scope Management: Can be placed at the file, namespace, or class level to control scope.




What is the purpose of the ‘default’ keyword in C#?

The default keyword is used in several contexts to provide a default value for a type or to specify a default case in a switch statement. Its purpose varies based on the context in which it is used.

// Syntax
T defaultValue = default(T); 

1) Default Value for a Type: Used to obtain the default value of a type, especially useful in generics.

int defaultInt = default(int); // 0 

2) Default Case in a Switch Statement: Specifies a case to execute when no other case matches.

switch (expression)
{
    case value1:
        // Code block
        break;
    default:
        // Code block
        break;
} 

3) Default Literal: A shorthand way to obtain the default value of a type (C# 7.1 and later).

int defaultInt = default; // 0 




What is the purpose of the ‘default’ literal in generic programming?

The default literal is used to provide a default value for generic types. It helps in initializing generic variables with a default value. Useful in generic methods to return default values for type parameters.





What is the use of the yield keyword in C#?

The yield keyword in C# is used in an iterator to provide a value to the enumerator object or to signal the end of the iteration. It simplifies the implementation of custom iteration over collections.

Uses of the ‘yield’ Keyword:

  1. yield return: Provides the next value in the iteration.
  2. yield break: Ends the iteration.

Benefits:

  • Simplifies Code: Reduces the complexity of writing custom iterators.
  • Lazy Evaluation: Values are generated on demand.
  • Maintains State: Automatically maintains the state of the iteration across multiple calls.




How do you implement an iterator in C#?

Iterators are methods, properties, or indexers that perform custom iteration over a collection. iterator is implemented using the yield return and yield break statements.



When to use iterator:

  • Custom Collection: You have a custom collection that you want to iterate over in a specific way.
  • Lazy Evaluation: You want to yield items one at a time as they are needed, rather than generating all items at once.
  • Complex Iteration Logic: The iteration logic is complex and involves multiple steps or conditions.

Suppose you have a tree data structure, and you want to iterate over its nodes in a specific order (e.g., depth-first search).





What is the ‘base’ keyword used for in C#?

The base keyword is used to access members of the base class from within a derived class. It allows derived classes to call methods, access properties, and invoke constructors of their base class.

Uses of ‘base’ Keyword:

  1. Calling Base Class Constructors: You can call a constructor of the base class from a constructor of the derived class.


  2. Accessing Base Class Members: You can access a method, property, indexer, or field of the base class that has been overridden or hidden in the derived class.



How do you declare and raise an event in C#?

Events are a way to provide notifications when something occurs. They are commonly used in scenarios where you want to notify other parts of your application about state changes or actions.

Steps to declare and raise event:

  • Define a Delegate
  • Declare the Event
  • Create a Method to Raise the Event
  • Raise the Event




What is a lambda expression in C#?

Provide a concise way to define anonymous methods. It allows you to write inline functions that can be passed as arguments to methods. Uses => operator with parameters on the left and the expression or statements on the right. Commonly used with delegates, LINQ queries, and event handling to simplify code and improve readability.




How do you handle exceptions in C#?

Exceptions are handled using try, catch, finally, and throw keywords. This mechanism helps in managing and responding to runtime errors in a controlled way.

  • try: Wraps code that might throw an exception.
  • catch: Catches and handles exceptions thrown in the try block.
  • finally: Contains code that runs after try and catch blocks, regardless of whether an exception was thrown.
  • throw: Used to throw an exception manually.




Can I have multiple ‘catch’ in exception handling?

Yes, you can have multiple catch blocks in exception handling. This allows you to handle different types of exceptions separately and provide specific logic for each exception type. The catch blocks are evaluated in the order they appear, so the most specific exceptions should be caught first, followed by more general exceptions.





What is the difference between ‘throw’ and ‘throw ex’ in C#?

The difference between throw and throw ex in C# lies in how they affect the exception’s stack trace when rethrowing an exception.

throw – Preserves Stack Trace: Using throw inside a catch block rethrows the current exception while preserving the original stack trace. This is useful for debugging, as it allows you to see the original point where the exception was thrown.

throw ex – Resets Stack Trace: Using throw ex resets the stack trace to the current location in the catch block. This means the stack trace will start from the point where the exception is rethrown, losing the original context.





How do you define a custom exception in C#?

A custom exception is a user-defined class that extends the Exception class. It allows you to create specific error types tailored to your application’s needs. Custom exceptions can include custom properties, methods, and constructors for more detailed error handling and messaging.





What is the difference between ref and out parameters in C#?


ref out
Must be initialized before being passed. Must be assigned in the called method before returning.
Can be used to read and modify the value. Used to output data from a method, not for input.
Allows passing a value to a method and modifying it within the method. Allows returning multiple values from a method.
ref keyword example below out keyword example below




What is the difference between ‘in’ and ‘out’ parameters?

The in and out keywords in C# are used to define how parameters are passed to methods. Both are special types of parameters, but they serve different purposes.


'in' Parameter 'out' Parameter
Used to pass arguments by reference, ensuring the method does not modify the argument's value. Used to pass arguments by reference, allowing the method to modify and return the value.
The argument must be initialized before being passed to the method. The argument does not need to be initialized before being passed; it must be assigned a value within the method.
The method cannot modify the value of the in parameter. The method must assign a value to the out parameter before it returns.
Use when you want to pass a large object by reference to avoid copying but still prevent modifications. Use when you need to return multiple values from a method or ensure a value is assigned inside the method.
Immutable within the method. Mutable within the method.




What is the ‘params’ keyword?

The params keyword allows you to specify a method parameter that takes a variable number of arguments. It is used to specify a parameter that takes an array of arguments, making it possible to pass a variable number of arguments without explicitly creating an array. It





How do you define and use Indexers in C#?

Indexers allow instances of a ‘class’ or ‘struct’ to be indexed just like arrays. They are defined using the this keyword followed by a parameter list inside square brackets. Indexers provide a way to access class or struct data in a similar way to accessing elements in an array.





How do you implement Generic Classes and Methods in C#?

Generics allow you to define classes, methods, and other data structures without specifying the exact data type. This enables code reusability and type safety.





What is the purpose of constraints in generic programming?

Constraints in generic programming allow developers to write more robust and versatile generic code by specifying the necessary conditions that type arguments must fulfill. It are used to enforce specific requirements on type parameters, ensuring type safety, enabling access to members, providing flexibility, and enhancing code clarity.

Types of Constraints:

  1. where T : struct: The type argument must be a value type.
  2. where T : class: The type argument must be a reference type.
  3. where T : new(): The type argument must have a parameterless constructor.
  4. where T : <base class name>: The type argument must be or derive from the specified base class.
  5. where T : <interface name>: The type argument must implement the specified interface.
  6. where T : U: The type argument must be or derive from the type argument U.




What are anonymous types in C#?

Anonymous types provide a way to create simple, immutable object types without having to explicitly define a class. They are useful for encapsulating a set of read-only properties into a single object for convenience, typically when you want to return multiple values from a method or perform quick data processing operations without the overhead of defining a new class. Typically used within the scope they are defined, such as within a method. Anonymous types are created using the new keyword followed by an object initializer syntax.

syntax:

var anonymousObject = new { Property1 = "Hello", Property2 = 123 }; 





What is the purpose of the var keyword?

The var keyword is used for implicitly typing local variables. It allows the compiler to infer the type of the variable from the right-hand side of the assignment at compile-time. The var keyword enhances code readability and reduces redundancy without sacrificing type safety.

example:

var number = 10; // The type of number is inferred as int



How do you use the dynamic keyword?

The dynamic keyword in C# provides a powerful mechanism for deferring type resolution until runtime, making it ideal for interacting with dynamic languages, COM objects, and scenarios where type information is not available at compile-time. While it offers significant flexibility, it should be used judiciously due to the performance overhead and potential for runtime errors.

Unlike var, which requires the type to be known at compile-time, dynamic variables are checked at runtime.


COM Interop Example:

// COM Interop Example
dynamic excelApp = Activator.CreateInstance(Type.GetTypeFromProgID("Excel.Application"));
excelApp.Visible = true;
excelApp.Workbooks.Add();
excelApp.Cells[1, 1].Value = "Hello, Excel!"; 

Disadvantages – Performance Overhead, Lack of IntelliSense, Potential for Runtime Errors.




What is ‘thread’ in C#?

A thread in C# is a basic unit of execution within a process, allowing concurrent operations. Each process can have multiple threads, which share the process’s resources but execute independently. Threads allow a program to perform multiple operations concurrently, making efficient use of CPU resources and improving application performance, especially for tasks that involve waiting or are computationally intensive. Creating a thread can be done using the Thread class in the System.Threading namespace. Provides Thread Safety, ensuring that multiple threads do not interfere with each other when accessing shared resources.

Multithreading: The ability to run multiple threads concurrently within the same process. It helps in performing complex or multiple tasks at the same time.

Thread Life Cycle:

  • Unstarted: The thread is created but not yet started.
  • Running: The thread is executing.
  • Blocked/Waiting: The thread is blocked or waiting for a resource or event.
  • Dead: The thread has finished execution or has been terminated.




What is asynchronous programming? (or) How do you use Task, async, await keywords in C#.

In C#, the Task, async, and await keywords are used for asynchronous programming. This approach is called “asynchronous programming” or “async/await programming.” It allows you to write code that performs tasks asynchronously, meaning the tasks run independently of the main application flow, without blocking it. This is especially useful for I/O-bound operations like file access, network calls, or database queries, as well as for CPU-bound operations that might take a long time to complete.

  • Task: Represents an asynchronous operation. It’s part of the Task Parallel Library (TPL) in the System.Threading.Tasks namespace.
  • async: Indicates that a method is asynchronous and can contain await expressions.
  • await: Pauses the execution of the async method until the awaited task completes.




What is the purpose of the ‘lock’ statement in C#?

The lock statement ensures that a block of code runs to completion by only one thread at a time. This prevents multiple threads from accessing a shared resource simultaneously (Thread Safety), which can lead to race conditions and data corruption. The lock statement provides a mechanism for enforcing thread synchronization, ensuring that only one thread can enter the critical section of code at any given moment. Helps avoid deadlocks by locking on a private object instead of this or a type.





Guidelines for using ‘lock’

  • Use a private object: Always use a private object for locking. Never lock on publicly accessible objects, instances of this, or types, as this can lead to unexpected behavior and deadlocks.
  • Keep the critical section small: Minimize the code inside the lock statement to reduce the chance of contention and improve performance.
  • Avoid locking on strings: Strings are immutable and interned by the CLR, which means that locking on a string can inadvertently lock on the same string instance across different parts of the code.



What is the purpose of the ‘is’ and ‘as’ operators?

The is and as operators in C# are used for type checking and type casting, respectively. They are useful for working with objects when you need to verify or convert their types at runtime.


‘is’ Operator: The is operator checks if an object is compatible with a given type. It returns true if the object can be cast to the specified type without throwing an exception; otherwise, it returns false.

if (obj is string) { } 

‘as’ Operator: The as operator attempts to cast an object to a specified type. If the cast is successful, it returns the object as the new type. If the cast fails, it returns null instead of throwing an exception.

string str = obj as string; 


is Operator as Operator
Checks if an object is of a certain type Casts an object to a specified type
Returns true or false Returns the object as the new type, or null
Does not throw exceptions Does not throw exceptions (returns null on failure)
Used for type checking Used for safe type casting



How do you use attributes in C#?

Attributes in C# provide a way to add metadata to your code. They can be applied to various code elements, such as classes, methods, properties, fields, and more. Attributes are used to store declarative information and can be accessed at runtime using reflection.





What is the purpose of the ‘AttributeUsage’ attribute?

The AttributeUsage attribute is used to specify the kinds of program elements to which a custom attribute can be applied. It allows you to control where and how your custom attribute can be used, and to define additional settings such as whether the attribute can be applied multiple times or inherited by derived classes.

Key Properties of ‘AttributeUsage’:

  1. ValidOn: Specifies the program elements (such as classes, methods, properties, etc.) to which the attribute can be applied using the AttributeTargets enum.
    example values: AttributeTargets.Class, AttributeTargets.Method, AttributeTargets.Property, etc.
  2. AllowMultiple: If true, the attribute can be applied more than once to the same element. The default value is false.
  3. Inherited: If true, the attribute can be inherited by derived classes or overriding members. The default value is false.




What is the difference between Shallow copy and Deep copy in C#?

Shallow Copy: Creates a new object but references the same objects as the original. In other words, it creates a new instance of the original object, but the fields of the new object still reference the same objects as the fields of the original object. Copies the top-level structure of the object.

Deep Copy: Creates a new object and recursively copies all objects it references. In other words, it creates a completely independent copy of the original object and all objects that the original object references. Copies the entire object graph.



Shallow Copy Deep Copy
Copies only the top-level structure Copies the entire object graph
References the same instances Creates new instances of referenced objects
Used when the object is simple or immutable Used when the object is complex and mutable
Generally faster Generally slower due to recursive copying



How do you implement ICloneable interface in C#?

The ICloneable interface in C# is used to create a clone (a copy) of an object. To implement it you need to define the Clone method, which returns a copy of the current instance. you can implement either a shallow copy or a deep copy.





What are nullable types in C#?

Nullable types allow value types (such as int, double, bool, etc.) to represent null values. This is useful when you need to represent the absence of a value for value types, which normally cannot be null.

A nullable type is declared using the ? syntax or the Nullable<T> generic type. For example, int? and Nullable<int> both represent a nullable integer.





What is the purpose of the ?? operator?

The ?? operator in C# is known as the null-coalescing operator. Its primary purpose is to provide a default value for nullable types or reference types when they are null.

The ?? operator returns the left-hand operand if it is not null; otherwise, it returns the right-hand operand.





How do you handle null values with nullable types?


  1. Using ‘HasValue’ Property: The HasValue property indicates whether a nullable type contains a non-null value.
  2. Using ‘Value’ Property: The Value property retrieves the value of the nullable type if ‘HasValue’ is ‘true’. Be cautious, as accessing ‘Value’ when ‘HasValue’ is ‘false’ will throw an ‘InvalidOperationException’.
  3. Using Null-Coalescing Operator (??): The null-coalescing operator (??) provides a default value if the nullable type is ‘null’.
  4. Using Null-Conditional Operator (?.): The null-conditional operator (?.) allows you to access members only if the operand is not ‘null’.
  5. Default Value with ‘GetValueOrDefault’: The GetValueOrDefault method returns the value if it is not ‘null’; otherwise, it returns the default value for the type.
  6. Using ‘is’ and Pattern Matching: Pattern matching with is allows checking and accessing the value if it is not ‘null’.



What is the difference between the == and Equals methods?


== Operator Equals Method
Type Operator Method
Purpose Compares references for reference types, and values for value types Compares values or contents of objects
Overridable Yes, can be overloaded in user-defined types Yes, can be overridden in user-defined types
Default Behavior Reference comparison for reference types, value comparison for value types Reference comparison (default for reference types)
Null Handling Can be used to compare null values Can be used to compare null values
Static/Dynamic Static, defined at compile-time Instance method, can use runtime polymorphism




How do you override the Equals method in C#?

Overriding the Equals method involves providing a custom implementation that defines how instances of your class should be compared for equality.

Steps to Override Equals Method:

  1. Override the Equals Method – Provide a custom implementation for the Equals method that compares the relevant fields of your object.
  2. Override GetHashCode Method – When overriding Equals, it is also important to override GetHashCode to ensure that objects that are considered equal have the same hash code.
  3. Implement IEquatable<T> Interface (Optional) – Implementing IEquatable<T> can improve performance and make your equality checks more explicit.




How do you implement the IComparable<T> interface?

IComparable<T> is particularly useful for sorting and comparison operations. The interface requires you to implement the CompareTo method, which compares the current instance with another object of the same type.





What is the purpose of the ‘global’ keyword in namespace declarations?

The global keyword is used in namespace declarations to reference the global namespace, ensuring that the namespace reference is unambiguous and starts from the root. This is particularly useful in scenarios where you might have nested or conflicting namespaces and it makes the code clearer.





What are ‘global using’ directives in C# 10.0?

Global using directives are a C# 10.0 feature that allows using directives to be declared once and applied globally to all files in a project. They simplify and clean up code by reducing the need for repetitive using statements.

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



What is Dependency Injection and How do you implement it in different ways in C#?

Dependency Injection (DI) is a design pattern used to achieve Inversion of Control (IoC) between classes and their dependencies. It allows the dependencies of a class to be injected at runtime, promoting decoupling and easier testing.

Key Components of Dependency Injection:

  1. Service: The class that performs some specific service.
  2. Client: The class that depends on the service.
  3. Injector: The mechanism that injects the service into the client.

3 Ways to Implement Dependency Injection:

  1. Constructor Injection: Dependencies are provided through a class constructor. This is the most commonly used type of dependency injection.
  2. Property Injection: Dependencies are provided through public properties of the client class. This type is less commonly used and typically for optional dependencies.
  3. Method Injection: Dependencies are provided through method parameters. This type is used when the dependency is only needed for a specific method.

Advantages:

  • Decoupling: Reduces tight coupling between classes.
  • Testability: Makes it easier to test by allowing mock implementations.
  • Flexibility: Promotes flexible and maintainable code architecture.



How do you use the Activator.CreateInstance method?

Activator.CreateInstance allows you to create instances of types at runtime. This method is particularly useful when the type of the object to be created is not known at compile time but is determined at runtime. It provides several overloads to support different scenarios, such as creating instances with parameters or using generic type parameters.





How do you use pattern matching in C#?

Pattern matching can be used with switch statements, if statements, and expressions. Pattern matching enhances type safety and readability, making code more expressive and easier to maintain.





What is the purpose of tuples in C#?

Tuples provide a way to store multiple values in a single object without creating a custom class or struct. They are useful for returning multiple values from a method, grouping related data, and making code more readable and concise.





How do you deconstruct a tuple in C#?

Deconstruction extracts the elements of the tuple into individual variables. You can deconstruct a tuple into separate variables to make it easier to work with the individual elements.





What happens if a constructor throws an exception in C#?

When a constructor throws an exception, the object construction fails and the following things happen:

  • Object Creation Fails: The partially created object is discarded, and the reference to the object becomes null (if the constructor was called with the new keyword).
  • Exception Propagation: The exception propagates up the call stack to the point where the constructor was called. If not caught, it continues to propagate until it is either caught by a catch block or the application terminates.
  • No Finalizers Called: Finalizers (destructors) are not called on the partially constructed object because it was never fully constructed. The garbage collector will eventually clean up any resources associated with the object.



What is an anonymous method in C#?

An anonymous method in C# is a method without a name, defined using the delegate keyword. It allows you to define inline methods that can be passed as parameters, used in event handling, or assigned to delegates without needing to declare a separate method.





What is the purpose of the ‘nameof’ operator in C#?

The nameof operator is used to obtain the name of a variable, type, or member as a string. It is useful for refactoring, code readability, and avoiding hardcoded strings, especially when dealing with exceptions, logging, or argument validation.

string propertyName = nameof(Example.PropertyName); 



What are expression-bodied members in C#?

Expression-bodied members in C# provide a concise syntax for defining methods, properties, constructors, destructors, and other members that can be implemented with a single expression. Expression-bodied members use the => (lambda expression) syntax to directly return or assign a value.

Traditional method syntax:

public int Add(int x, int y)
{
	return x + y;
}

Expression-bodied method:

public int AddExpressionBodied(int x, int y) => x + y; 



What is the purpose of the Span<T> type in C#?

The Span<T> type provides a safe and efficient way to work with contiguous memory regions. It is a stack-allocated type, meaning it’s a lightweight, value type that helps avoid heap allocations. Span<T> is particularly useful in scenarios requiring high performance and low memory overhead, such as processing large data streams or performing operations on buffers, systems programming, game development, or processing large datasets.

Allows for creating sub-spans (slices) of the original span without copying data, providing a view over a portion of the memory.

ReadOnlySpan<T> is a read-only counterpart, used when you need a non-modifiable view of the data.





What is the purpose of the ‘stackalloc’ keyword in C#?

The stackalloc keyword is used to allocate memory on the stack for temporary arrays or spans. It improves performance by avoiding heap allocations (which is faster and more efficient) and reducing garbage collection overhead.

Span<int> numbers = stackalloc int[5];
// or
Span<int> numbers = stackalloc int[3] { 10, 20, 30 }; 



What is the purpose of Memory<T> and ReadOnlyMemory<T>?

Memory<T> and ReadOnlyMemory<T> are types designed to represent a contiguous region of memory in a safe and efficient manner. They allow for working with large data buffers, slices of arrays, or other memory blocks without the need for copying data. They are especially useful in performance-critical applications where minimizing memory allocations and copying is important.

Purpose of Memory<T>:

  • Writable Memory: Memory<T> represents a block of memory that can be read from and written to. It is similar to Span<T>, but Memory<T> can be stored on the heap, while Span<T> is restricted to stack-only scenarios.
  • Slicing: Allows you to create sub-slices of the memory without copying the underlying data.
  • Asynchronous (Async/Await) Operations: Unlike Span<T>, Memory<T> can be used in async methods. Efficiently manage buffers in scenarios like network I/O, file I/O, or data processing where copying data would be costly.

Purpose of ReadOnlyMemory<T>:

  • Read-Only Memory: ReadOnlyMemory<T> is similar to Memory<T>, but it only allows reading from the memory. It ensures that the underlying data cannot be modified, which is useful for enforcing immutability.
  • Data Security: Provides a way to pass around slices of data safely, ensuring that the original data cannot be altered by the recipient.
  • Immutable Data: Use ReadOnlyMemory<T> when you want to ensure that a section of data remains unchanged when passed to other parts of the code.




What is the difference between ‘Task’ and ‘ValueTask’ in C#?

Task and ValueTask are both used in C# for representing asynchronous operations, but they serve slightly different purposes and are optimized for different scenarios.

Task ValueTask
Purpose Represents an asynchronous operation. Always allocates memory on the heap. Represents an asynchronous operation that may or may not involve heap allocation.
Memory Allocation Always allocates memory on the heap, even if the operation is already complete. Avoids heap allocation when the result is already available or the operation is simple.
Return Value Cannot directly return a value for a completed operation (must use Task.FromResult). Can directly return a result or a Task, optimizing for performance in cases where the result is already available. (frequently-called methods that often return a completed result)
Reusability Task instances are reusable. ValueTask should not be awaited more than once or used in multiple continuations.
Error Handling Errors are stored inside the Task. Errors are stored inside the ValueTask, similar to Task, but need careful handling to avoid misuse.
Use Cases General-purpose, widely used for async operations or if you expect the operation to involve multiple await/continuation scenarios and you don’t need to optimize for every possible allocation. Best for high-performance scenarios where avoiding allocations is critical, and the result is often synchronous, or the operation is simple.
Overhead Higher overhead due to heap allocation. Lower overhead when the operation is synchronous or short-lived.




How do you use the ‘record’ feature in C# 9.0?

The record feature in C# 9.0 introduces a new reference type that provides built-in functionality for immutable data models with value-based equality, making it easier to create data-centric classes.

Key Features of ‘record’:

  1. Immutability: By default, records are immutable, meaning once created, their properties cannot be changed.
  2. Value-Based Equality: Records compare objects based on their values, not their references, making them ideal for data structures where the value matters more than the identity.
  3. Readability: Use when you need concise and readable code for defining types that primarily store data.
  4. Concise Syntax: Records can be declared with a much simpler syntax compared to traditional classes.




How do you implement ‘with’ expressions in C# 9.0 records?

In C# 9.0, records provide a simple way to create immutable objects with value-based equality. The with expression allows you to create a copy of an existing record object with some properties changed, while the original object remains unchanged.





What is a ‘Record Structin C# 10.0?

Unlike regular records, which are reference types, a record struct is a value type. This means that it is stored on the stack and passed by value rather than by reference. By default, record structs are designed to be immutable. This makes them useful for defining small, lightweight data structures that should not change after creation.

public record struct Point(int X, int Y); 



What is a target-typed ‘new’ expression in C# 9.0?

A target-typed new expression in C# 9.0 allows you to create an instance of an object without explicitly specifying the type when the type can be inferred from the context. This feature simplifies the syntax, making the code cleaner and more concise. The compiler infers the type of the object being created based on the context, so you don’t need to repeat the type on the right-hand side of the assignment.

List<int> numbers = new(); // List<int> is inferred



What is the ‘init’ accessor in C# 9.0?

The init accessor in C# 9.0 is a new way to set properties during object initialization, making them immutable after the object is created. This means once an object is created, properties with init accessors cannot be modified afterward.





How do you use the ‘range’ and ‘index’ operators

The range and index operators in C# are used to easily access specific elements or ranges of elements within arrays, strings, or other indexable collections.

1) Range Operator (..): The range operator (..) allows you to specify a range of elements. The syntax start..end extracts elements from the start index to the end index (exclusive). You can omit the start or end to take elements from the beginning or up to the end of the collection.



2) Index Operator (^): The index operator ^ allows you to access elements from the end of a collection. The syntax ^n refers to the element at the n-th position from the end.





What is the purpose of the ‘checked’ and ‘unchecked’ keywords in C#?

The checked and unchecked keywords in C# are used to control the behavior of arithmetic operations and conversions with respect to overflow.

1) ‘checked’ Keyword: Enforces overflow checking and throws an exception if overflow occurs. Ensures data integrity by detecting overflows, particularly in critical calculations where overflow could lead to incorrect results. Often used in scenarios where arithmetic operations involve user input or data that could reach extreme values.

// This will throw an OverflowException
int result = checked(max + 1); 

2) ‘unchecked’ Keyword: Disables overflow checking, allowing arithmetic operations to wrap around without throwing an exception. Improves performance by avoiding the overhead of overflow checking.
Useful in scenarios where you are confident that overflow is either impossible or acceptable (e.g., when working with bitwise operations).

int max = int.MaxValue;

// This will not throw an exception; it will wrap around
int result = unchecked(max + 1); 

// Output: -2147483648 (wrapped around value)
Console.WriteLine(result); 



What is the purpose of the ‘volatile’ keyword in C#?

The volatile keyword in C# is used to indicate that a field may be modified by multiple threads simultaneously. It ensures that the most up-to-date value of the field is always read from memory, not from a CPU register or cache. Use the volatile keyword for fields that are shared between multiple threads and where simple atomic reads and writes (like int, bool, float, etc.) are required.


It’s not suitable for more complex thread synchronization scenarios (like incrementing a value or checking and setting a value simultaneously); for those, you should use lock, Monitor, Mutex, etc.




How do you use ‘string interpolation’ in C#?

String interpolation allows you to embed expressions directly within string literals, making it easier and more readable to format strings. Use the $ symbol before the string and place expressions inside curly braces {} within the string.

string name = "John";
int age = 30;
string message = $"My name is {name} and I am {age} years old."; 




Download all Questions as .PDF


loading…

  1. Anonymous says:

    amazing list of questions. Thanks bro keep it up

Leave a Reply

Your email address will not be published. Required fields are marked *