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!