Preparing for a technical interview can be daunting, especially when you're aiming to demonstrate your expertise as a C# developer. To help you get ready, we've compiled a list of five intermediate-level questions that are commonly asked in technical interviews. By familiarizing yourself with these topics, you'll be better equipped to tackle challenging questions and impress your interviewers.
Question 1: Explain the difference between abstract class and interface in C#.
Understanding the difference between abstract classes and interfaces is fundamental for C# developers, as both are used to define contracts and provide polymorphic behavior.
Abstract Class:
Can have both abstract methods (without implementation) and non-abstract methods (with implementation). Can contain fields, constructors, and destructors. Can provide default behavior. A class can inherit only one abstract class (single inheritance).
Interface:
Can only have method signatures (methods without implementation), properties, events, and indexers. Cannot contain fields, constructors, or destructors. Cannot provide any default behavior. A class or struct can implement multiple interfaces (multiple inheritance).
Example:
public abstract class Animal
{
public abstract void MakeSound();
public void Sleep()
{
Console.WriteLine("Sleeping");
}
}
public interface IFlyable
{
void Fly();
}
public class Bird : Animal, IFlyable
{
public override void MakeSound()
{
Console.WriteLine("Chirp");
}
public void Fly()
{
Console.WriteLine("Flying");
}
}
Question 2: What is LINQ and how does it work in C#?
LINQ (Language Integrated Query) is a powerful feature in C# that allows you to query collections in a declarative manner, similar to SQL. LINQ can be used with various data sources such as arrays, collections, XML, and databases.
Key Features:
Provides a consistent query syntax across different data sources. Supports filtering, ordering, and grouping operations. Enables strong typing and IntelliSense support in Visual Studio.
Example:
var numbers = new List<int> { 1, 2, 3, 4, 5 };
var evenNumbers = from num in numbers
where num % 2 == 0
select num;
foreach (var num in evenNumbers)
{
Console.WriteLine(num);
}
Question 3: Explain the concept of async and await in C#.
Asynchronous programming is crucial for improving the responsiveness of applications, especially in scenarios involving I/O-bound operations. The async and await keywords in C# simplify writing asynchronous code.
Key Points:
async keyword marks a method as asynchronous. await keyword is used to suspend the execution of an async method until the awaited task completes. The method marked with async must return Task, Task<T>, or void.
Example:
public async Task<string> GetDataAsync()
{
using (var client = new HttpClient())
{
var response = await client.GetStringAsync("https://example.com/data");
return response;
}
}
Question 4: What is Dependency Injection and how is it implemented in C#?
Dependency Injection (DI) is a design pattern used to achieve Inversion of Control (IoC) between classes and their dependencies. It enhances code reusability, testability, and maintainability.
Key Concepts:
- Constructor Injection: Dependencies are provided through a class constructor.
- Property Injection: Dependencies are set through public properties.
- Method Injection: Dependencies are passed through method parameters.
Implementing DI in C#:
C# provides built-in support for DI through the Microsoft.Extensions.DependencyInjection namespace.
Example:
public interface IMessageService
{
void SendMessage(string message);
}
public class EmailService : IMessageService
{
public void SendMessage(string message)
{
Console.WriteLine($"Email sent: {message}");
}
}
public class Notification
{
private readonly IMessageService _messageService;
public Notification(IMessageService messageService)
{
_messageService = messageService;
}
public void Notify(string message)
{
_messageService.SendMessage(message);
}
}
// Setup DI
var services = new ServiceCollection();
services.AddTransient<IMessageService, EmailService>();
services.AddTransient<Notification>();
var serviceProvider = services.BuildServiceProvider();
// Resolve and use the service
var notification = serviceProvider.GetService<Notification>();
notification.Notify("Hello, Dependency Injection!");
Question 5: How does garbage collection work in C#?
Garbage collection (GC) in C# is an automatic memory management feature that reclaims memory occupied by objects that are no longer in use, preventing memory leaks and optimizing the use of system resources.
Key Concepts:
- Generation 0, 1, and 2: Objects are categorized into three generations. Generation 0 is for short-lived objects, and Generation 2 is for long-lived objects.
- Managed Heap: The area of memory where the GC allocates and deallocates memory.
- GC Roots: Objects referenced directly from application roots, such as static fields and local variables, are considered alive.
How GC Works:
- Mark Phase: GC identifies which objects are still reachable (alive).
- Sweep Phase: GC reclaims memory occupied by unreachable objects.
- Compacting Phase: GC compacts the heap to reduce fragmentation.
Example:
class Program
{
static void Main()
{
for (int i = 0; i < 100; i++)
{
CreateObject();
}
GC.Collect(); // Forces garbage collection
GC.WaitForPendingFinalizers(); // Waits for finalizers to complete
}
static void CreateObject()
{
var obj = new object();
// obj goes out of scope here and becomes eligible for GC
}
}
Final Thoughts
Being well-prepared for a technical interview involves more than just knowing the right answers. It requires a deep understanding of core concepts and the ability to apply them effectively. These five questions cover important areas in C# development and will help you showcase your skills and knowledge confidently. Good luck with your interview!