.NET Interview Questions

Created
Aug 22, 2024 02:41 AM

Glossary

.NET - . represents OOO and NET is Network Enabled Technology
BCL - Base Common Libraries
CLR - Common Language Runtime
MSIL - Microsoft Intermediate Language
Assembly - Assemblies are the building block of .NET framework applications; they form the fundamental unit of deployment, version control, reuse, activation scoping and security permissions.
.EXE - executable e.g., compiling a Console Application
DLL - Dynamic Link Library e.g., compiling a Class Library Project
Technologies supported by the .NET framework are as follows
  1. ASP.NET (Active Server Pages.NET)
  1. ADO.NET (Active Data Object.NET)
  1. WCF (Windows Communication Foundation)
  1. WPF (Windows Presentation Foundation)
  1. WWF (Windows Workflow Foundation)
  1. AJAX (Asynchronous JavaScript and XML)
  1. LINQ (Language Integrated Query)
  1. ASP.NET MVC (Model View Controller)
  1. ASP.NET WEB API
Compiler
  1. JIT - Just in Time
  1. AOT - Ahead of Time

.NET Versions

.NET Framework 1.0

  • Key Features: Garbage collection, generics, reflection, threading, security, and interoperability with COM.

.NET Framework 1.1

  • Key Features: Bug fixes, performance improvements, and support for XML Web Services.

.NET Framework 2.0

  • Key Features: Introduction of Windows Forms 2.0, ASP.NET 2.0, Windows Communication Foundation (WCF), ADO.NET 2.0, and Workflow Foundation.

.NET Framework 3.0

  • Key Features: Added support for ADO.NET Entity Framework, Windows Presentation Foundation (WPF), and Workflow Foundation.

.NET Framework 3.5

  • Key Features: Enhanced support for WPF, WCF, and ADO.NET Entity Framework.

.NET Framework 4.0

  • Key Features: Asynchronous programming support, dynamic language support, and improved performance.

.NET Framework 4.5

  • Key Features: Enhanced support for mobile devices, cloud computing, and web development.

.NET Framework 4.6

  • Key Features: Support for the Universal Windows Platform (UWP) and improved performance.

.NET Framework 4.7

  • Key Features: Support for the .NET Native program, performance enhancements, and various bug fixes.

.NET Framework 4.8

  • Key Features: Support for Windows 10, performance improvements, and additional bug fixes.

.NET 6

  • Key Features: Cross-platform capabilities, HTTP/3 support, Hot Reload functionality, and enhancements to C# 10 and F# 6.
  • Minimal APIs: Simplified syntax for creating APIs with fewer lines of code.
  • Implicit global usings: Automatically includes commonly used namespaces.
  • File-scoped namespace declarations: Allows declaring a namespace for the entire file without additional indentation.
  • Performance improvements: Enhancements in garbage collection, JIT compilation, and various runtime optimizations.
  • Hot Reload: Enables developers to see changes in their code without restarting the application.
  • New JSON APIs: Improved System.Text.Json for better performance and functionality.

.NET 7

  • Key Features: Improved performance, new APIs, and enhanced cloud capabilities.
  • Improved performance: Further optimizations in the runtime and libraries.
  • New APIs for collections: Enhancements to System.Collections.Generic with new collection types.
  • File IO improvements: More efficient file handling and I/O operations.
  • Enhanced support for cloud-native apps: Features aimed at improving the development of applications for cloud environments.

.NET 8

  • Key Features: Full-stack Blazor support, improvements to .NET MAUI, enhanced diagnostics, new C# 12 features, and better performance and garbage collection
  • Native AOT (Ahead-of-Time compilation): Allows applications to be compiled into native code for faster startup times.
  • Improved container support: Enhancements for building and deploying containerized applications.
  • New diagnostics tools: Better tools for performance monitoring and debugging.
  • Enhanced security features: Improvements in security protocols and practices within the framework.

.NET 9

  • Faster exceptions: Exceptions are now 2-4x faster in .NET 9.
  • Caching improvements with HybridCache: HybridCache provides stampede protection and configurable serialization, resulting in up to 1000x performance improvement in high cache hit rate scenarios.
  • Garbage collection dynamic adaptation to application size: A new feature used by default instead of Server GC.
  • Numerous performance improvements: Including loop optimizations, inlining, and Arm64 vectorization and code generation.
  • System.Text.Json enhancements: New options to customize indentation character and size, and a new JsonSerializerOptions.Web singleton for web defaults.
  • New LINQ methods: CountBy and AggregateBy to aggregate state by key without needing to allocate intermediate groupings via GroupBy.
  • New collection types: System.Collections.Generic.PriorityQueue and System.Collections.Generic.OrderedDictionary

Dependency Injection in .NET

Dependency Injection (DI) is a design pattern widely used in .NET applications to achieve Inversion of Control (IoC) between classes and their dependencies. This pattern enhances code maintainability, testability, and flexibility by decoupling the creation of an object from its usage. Here's a detailed explanation of Dependency Injection in .NET, including its types, benefits, and how it is implemented.

What is Dependency Injection?

In Dependency Injection, a class (often referred to as a consumer) receives its dependencies (other classes or services it needs to function) from an external source rather than creating them internally. This approach allows for better separation of concerns and makes it easier to manage dependencies.

Key Concepts

  • Dependency: An object that another object depends on.
  • Inversion of Control (IoC): A principle where the control of object creation and management is transferred from the consumer to an external entity (like a DI container).
  • Service Container: A central location where services (dependencies) are registered and resolved.
  • Dependency Lifecycle: The lifetime of a dependency, which determines how instances are created and managed.

Benefits of Dependency Injection

  1. Loose Coupling: Classes are less dependent on concrete implementations, making it easier to change or replace dependencies without modifying the consumer class.
  1. Improved Testability: Dependencies can be easily mocked or stubbed, allowing for more straightforward unit testing.
  1. Centralized Configuration: All dependencies are configured in one place, making it easier to manage and understand the application's architecture.
  1. Enhanced Maintainability: Changes in dependencies require minimal changes in the consumer classes, leading to easier maintenance.

Types of Dependency Injection

  1. Constructor Injection: Dependencies are provided through the class constructor. This is the most common form of DI.
  1. Setter Injection: Dependencies are provided through public properties or setter methods. This allows for optional dependencies.
  1. Interface Injection: The dependency provides an injector method that will inject the dependency into any client that passes itself to the injector.

Dependency Lifecycles

In .NET, there are three primary lifecycles for dependencies when using Dependency Injection (DI): Singleton, Scoped, and Transient. Each of these lifecycles determines how instances of services are created and managed throughout the application's lifetime.
  1. Singleton: A Singleton service is created once and shared throughout the entire application. The same instance is used every time the service is requested.
  1. Scoped: A Scoped service is created once per request (or per scope). In a web application, this typically means one instance per HTTP request.
  1. Transient: A Transient service is created each time it is requested. A new instance is provided every time the service is requested from the DI container.

Implementing Dependency Injection in .NET

.NET provides a built-in IoC container that simplifies the management of dependencies. Here's how to implement DI in a .NET Core application:
  1. Registering Services: Services are registered in the IServiceCollection during application startup, specifying their lifecycle.
    1. public void ConfigureServices(IServiceCollection services) { services.AddSingleton<IMessageWriter, MessageWriter>(); services.AddScoped<IMyService, MyService>(); services.AddTransient<ITransientService, TransientService>(); }
  1. Resolving Services: Services can be resolved using constructor injection in controllers or other services.
    1. public class MyController : Controller { private readonly IMyService _myService; public MyController(IMyService myService) { _myService = myService; } }
  1. Running the Application: The application can be run using the Host class, which manages the service provider.
    1. public static IHostBuilder CreateHostBuilder(string[] args) => Host.CreateDefaultBuilder(args) .ConfigureServices((hostContext, services) => { services.AddHostedService<Worker>(); });

Keyed Services in .NET 8

What are Keyed Services?
Keyed services enable the registration and resolution of services based on a specific key. This means you can register multiple implementations of the same service interface, each associated with a unique key, and then retrieve the desired implementation at runtime using that key. This approach simplifies managing different implementations without needing complex factory patterns or service locators.

How to Register Keyed Services

To resolve a keyed service, you can use the [FromKeyedServices] attribute in the constructor of the class that requires the service. Here’s an example:
public class ExampleService { public ExampleService([FromKeyedServices("queue")] IMessageWriter writer) { // Use the writer implementation based on the key } }

Benefits of Keyed Services

  1. Flexibility: Keyed services provide a more flexible way to manage multiple implementations of the same interface without the need for complex factory methods.
  1. Simplified Code: By using keyed services, you can reduce boilerplate code associated with creating and managing factories or service locators.
  1. Enhanced Readability: The use of keys makes it clear which implementation is being used, improving the readability of the code.

Use Cases for Keyed Services

  • Multiple Implementations: When you have different implementations of an interface that need to be resolved based on specific criteria (e.g., different storage mechanisms like local and cloud storage).
  • Dynamic Behavior: When the behavior of a service needs to change based on runtime conditions, keyed services allow you to switch implementations easily.

Example of Keyed Services in Action

Here’s a complete example demonstrating the use of keyed services in a .NET 8 application:
public interface IMessageWriter { void Write(string message); } public class MemoryMessageWriter : IMessageWriter { public void Write(string message) { Console.WriteLine("Memory: " + message); } } public class QueueMessageWriter : IMessageWriter { public void Write(string message) { Console.WriteLine("Queue: " + message); } } public class ExampleService { private readonly IMessageWriter _writer; public ExampleService([FromKeyedServices("queue")] IMessageWriter writer) { _writer = writer; } public void SendMessage(string message) { _writer.Write(message); } } // In Startup.cs or Program.cs public void ConfigureServices(IServiceCollection services) { services.AddKeyedSingleton<IMessageWriter, MemoryMessageWriter>("memory"); services.AddKeyedSingleton<IMessageWriter, QueueMessageWriter>("queue"); services.AddTransient<ExampleService>(); } // Usage var serviceProvider = services.BuildServiceProvider(); var exampleService = serviceProvider.GetRequiredService<ExampleService>(); exampleService.SendMessage("Hello, Keyed Services!");

QnA

What’s the difference between IEnumerable<T> and List<T>?

  1. IEnumerable is an interface, whereas List is one specific implementation of IEnumerable. A list is a class.
  1. FOR-EACH loop is the only possible way to iterate through a collection of IEnumerable whereas List can be iterated using several ways.
  1. IEnumerable doesn’t allow random access, whereas List does allow random access using the integral index.
  1. In general, from a performance standpoint, iterating through IEnumerable is much faster than iterating through a List.

What's the lifecycle of a dotnet application?

ASP.NET Application Lifecycle
Application Start: The lifecycle begins when a user makes a request to the web server. The Application_Start method is executed, setting global variables to their default values.
Object Creation: The web server creates instances of HttpContextHttpRequest, and HttpResponse. These objects hold information about the current request, including cookies and browser details.
HttpApplication Creation: An HttpApplication object is created to handle subsequent requests. Each web application has its own instance of this object.
Request Processing: The request is processed by the HttpApplication, which raises various events during this process.
Dispose: Before the application instance is destroyed, the Dispose method is called to release unmanaged resources.
Application End: Finally, the application is unloaded from memory, marking the end of its lifecycle.
ASP.NET Page Lifecycle
Page Request: The server checks if the page is being requested for the first time or if it can serve a cached version.
Page Initialization: All controls on the page are initialized.
Page Load: The page is populated with default values.
Validation: Any validation rules are applied to the page controls.
Postback Event Handling: If the page is being reloaded due to a postback (e.g., a form submission), the corresponding event handlers are executed.
Page Rendering: The final output is prepared and sent to the client.
Unload: After the response is sent, the page objects are removed from memory.
.NET Core Application Lifecycle
Initialization: The .NET Core application starts with the creation of a host process, which loads the application's dependencies and prepares the runtime environment.
Configuration: The application's configuration settings are loaded, including service registrations and middleware configurations.
Startup: The Startup class is invoked, where services are configured and the application pipeline is set up.
Request Handling: The application processes incoming requests through middleware components, which can handle requests, responses, and errors.
Shutdown: Upon termination, the application can clean up resources and perform any necessary finalization tasks