This article is perfect for anyone wanting to prove their .NET expertise! Hello .NET Developers, In this article, I’ll explore different C# concepts that every developer must know. It's always a great idea to test your knowledge and I’ve put together a few examples in this article with explanations and code examples. If you know and understand the code examples, you’re likely doing quite well in the .NET. 1. Difference between IEnumerable<T> vs. ICollection<T> While writing logic in C#, developers frequently encounter IEnumerable<T> and ICollection<T>. They may look quite similar but they serve different purposes in software development. IEnumerable<T> acts as the base interface for non-generic collections. It helps to iterate over a collection of a defined type. Good to have a lightweight collection which is more secure, as data manipulation is not allowed. Any collection if you want to prevent data manipulation, its recommended to use IEnumerable<T> IEnumerable<int> numbers = new List<int> { 1, 2, 3 }; foreach (var number in numbers) { Console.WriteLine(number); // Outputs: 1 2 3 } ICollection<T> extends IEnumerable<T> allows modifications with the help of alteration methods. This interface consists of methods to add, remove and check counts in the collection. ICollection<int> data = new List<int> { 12,43,556}; numbers.Add(4); Console.WriteLine(data.Count); // Outputs: 4 It is recommended to ICollection<T> when alter methods are required for the collection and IEnumerable<T> for simple read actions. 2. The Role of Dependency Injection in .NET Core It’s recommended to use a DI design pattern when you want to write loosely coupled & testable code, i. With DI, developers can manage dependencies between classes easily. .NET Core has built-in support for DI, making it easy to implement. How a developer can implement DI in C# Register services in the ConfigureServices method of your Startup.cs file. This is where you define which services will be available for injection. public void ConfigureServices(IServiceCollection services) { // Register a transient service services.AddTransient<IMyService, MyService>(); } Inject services into your classes through constructor injection. This ensures that your classes receive their dependencies without needing to create them directly. public class MyController : Controller { private readonly IMyService _myService; public MyController(IMyService myService) { _myService = myService; } public IActionResult Index() { var data = _myService.GetData(); return View(data); } } A code is more maintainable and testable when a developer decouples the creation of services. 3. The Difference Between ref and out Parameters In C#, ref and out are used to pass parameters by reference, but they have distinct characteristics. ref parameters require that the variable be initialized before it is passed to a method. The method can then modify the variable’s value. public void UpdateValue(ref int number) { number += 10; } int myNumber = 5; UpdateValue(ref myNumber); Console.WriteLine(myNumber); // Outputs: 15 out parameters do not require initialization before being passed. The method must assign a value to the out parameter before it returns. public void GetValues(out int value1, out int value2) { value1 = 10; value2 = 20; } GetValues(out int a, out int b); Console.WriteLine(a); // Outputs: 10 Console.WriteLine(b); // Outputs: 20 ref is typically used when a method needs to modify an existing variable, while out is used when a method needs to return multiple values or initialize values that were not provided by the caller. 4. Async and Await: Improving Application Performance In .NET, asynchronous programming is essential for writing efficient applications that perform well under load. The async and await keywords simplify working with asynchronous operations. async methods allow you to perform tasks asynchronously. Mark a method with the async keyword to enable the use of await inside it. public async Task<string> FetchDataAsync() { await Task.Delay(1000); // Simulates an asynchronous operation return "Data fetched"; } await helps application UI by not blocking the main thread. public async Task ShowDataAsync() { string data = await FetchDataAsync(); Console.WriteLine(data); } If you want improve performance of your application use async and await effectively and at the same time keeping application UI responsive. 5. Exception Handling in .NET Core Applications Handling exceptions gracefully is crucial for maintaining robust and user-friendly applications. .NET Core provides various mechanisms for exception handling. Local exception handling: Use try-catch blocks to catch and handle exceptions. try { int result = 10 / 0; // This will throw a DivideByZeroException } catch (DivideByZeroException ex) { Console.WriteLine("An error occurred: " + ex.Message); } Global exception handling in ASP.NET Core can be managed using middleware. Catch all types of exceptions in a common place which helps developers to manage user-friendly/common error messages for users. public void Configure(IApplicationBuilder app) { app.UseExceptionHandler("/Home/Error"); } Global exception handling middleware provides a common place to handle all application errors and exceptions. It ensures application consistently handles responses. 6. The Role of appsettings.json ASP.NET Core The appsettings.json file is used for managing application credentials, such as configuration strings and other application-specific keys. The configuration settings can be divided as per environments too Example appsettings.json file: { "ConnectionStrings": { "DefaultConnection": "Server=myServerAddress;Database=myDataBase;User Id=myUsername;Password=myPassword;" }, "Logging": { "LogLevel": { "Default": "Warning" } } } Accessing configuration values in your application is straightforward using the built-in configuration system. public class MyService { private readonly string _connectionString; public MyService(IConfiguration configuration) { _connectionString = configuration.GetConnectionString("DefaultConnection"); } } The appsettings.json file allows for easily fetch configuration settings, needs to handled efficiently. 7. Understanding Task vs. Thread in C# Both Task and Thread are used for concurrent programming in C#, but they serve different purposes. Thread represents a single path of execution and is a lower-level construct. It provides more control over the execution but requires manual management. Thread thread = new Thread(() => { Console.WriteLine("Running on a new thread"); }); thread.Start(); Task provides an abstract functionality to implement async operations and is used along with async/await. Task.Run(() => { Console.WriteLine("Running asynchronously"); }); Tasks simplify the management of asynchronous operations and are often the preferred choice for modern C# development. Access the complete C# .Net Interview Series So, how did you do? If you know the concept with confidence and understand the code examples, you’re likely well-versed in .NET. Let’s keep the conversation going and help each other grow as .NET professionals. Happy coding! This article is perfect for anyone wanting to prove their .NET expertise! This article is perfect for anyone wanting to prove their .NET expertise! Hello .NET Developers, Hello .NET Developers, In this article, I’ll explore different C# concepts that every developer must know. It's always a great idea to test your knowledge and I’ve put together a few examples in this article with explanations and code examples. If you know and understand the code examples, you’re likely doing quite well in the .NET. If you know and understand the code examples, you’re likely doing quite well in the .NET. 1. Difference between IEnumerable<T> vs. ICollection<T> While writing logic in C# , developers frequently encounter IEnumerable<T> and ICollection<T>. They may look quite similar but they serve different purposes in software development. C# IEnumerable<T> acts as the base interface for non-generic collections. It helps to iterate over a collection of a defined type. IEnumerable<T> acts as the base interface for non-generic collections. It helps to iterate over a collection of a defined type. IEnumerable<T> Good to have a lightweight collection which is more secure, as data manipulation is not allowed. Any collection if you want to prevent data manipulation, its recommended to use IEnumerable<T> IEnumerable<T> IEnumerable<int> numbers = new List<int> { 1, 2, 3 }; foreach (var number in numbers) { Console.WriteLine(number); // Outputs: 1 2 3 } IEnumerable<int> numbers = new List<int> { 1, 2, 3 }; foreach (var number in numbers) { Console.WriteLine(number); // Outputs: 1 2 3 } ICollection<T> extends IEnumerable<T> allows modifications with the help of alteration methods. This interface consists of methods to add, remove and check counts in the collection. ICollection<T> extends IEnumerable<T> allows modifications with the help of alteration methods. This interface consists of methods to add, remove and check counts in the collection. ICollection<T> extends IEnumerable<T> allows modifications with the help of alteration methods. This interface consists of methods to add, remove and check counts in the collection. ICollection<T> ICollection<int> data = new List<int> { 12,43,556}; numbers.Add(4); Console.WriteLine(data.Count); // Outputs: 4 ICollection<int> data = new List<int> { 12,43,556}; numbers.Add(4); Console.WriteLine(data.Count); // Outputs: 4 It is recommended to ICollection<T> when alter methods are required for the collection and IEnumerable<T> for simple read actions. It is recommended to ICollection<T> when alter methods are required for the collection and IEnumerable<T> for simple read actions. 2. The Role of Dependency Injection in .NET Core It’s recommended to use a DI design pattern when you want to write loosely coupled & testable code, i. With DI, developers can manage dependencies between classes easily. .NET Core has built-in support for DI, making it easy to implement. How a developer can implement DI in C# Register services in the ConfigureServices method of your Startup.cs file. This is where you define which services will be available for injection. Register services in the ConfigureServices method of your Startup.cs file. This is where you define which services will be available for injection. Register services public void ConfigureServices(IServiceCollection services) { // Register a transient service services.AddTransient<IMyService, MyService>(); } public void ConfigureServices(IServiceCollection services) { // Register a transient service services.AddTransient<IMyService, MyService>(); } Inject services into your classes through constructor injection. This ensures that your classes receive their dependencies without needing to create them directly. Inject services into your classes through constructor injection. This ensures that your classes receive their dependencies without needing to create them directly. Inject services public class MyController : Controller { private readonly IMyService _myService; public MyController(IMyService myService) { _myService = myService; } public IActionResult Index() { var data = _myService.GetData(); return View(data); } } public class MyController : Controller { private readonly IMyService _myService; public MyController(IMyService myService) { _myService = myService; } public IActionResult Index() { var data = _myService.GetData(); return View(data); } } A code is more maintainable and testable when a developer decouples the creation of services. A code is more maintainable and testable when a developer decouples the creation of services. 3. The Difference Between ref and out Parameters In C#, ref and out are used to pass parameters by reference, but they have distinct characteristics. ref parameters require that the variable be initialized before it is passed to a method. The method can then modify the variable’s value. ref parameters require that the variable be initialized before it is passed to a method. The method can then modify the variable’s value. ref public void UpdateValue(ref int number) { number += 10; } int myNumber = 5; UpdateValue(ref myNumber); Console.WriteLine(myNumber); // Outputs: 15 public void UpdateValue(ref int number) { number += 10; } int myNumber = 5; UpdateValue(ref myNumber); Console.WriteLine(myNumber); // Outputs: 15 out parameters do not require initialization before being passed. The method must assign a value to the out parameter before it returns. out parameters do not require initialization before being passed. The method must assign a value to the out parameter before it returns. out public void GetValues(out int value1, out int value2) { value1 = 10; value2 = 20; } GetValues(out int a, out int b); Console.WriteLine(a); // Outputs: 10 Console.WriteLine(b); // Outputs: 20 public void GetValues(out int value1, out int value2) { value1 = 10; value2 = 20; } GetValues(out int a, out int b); Console.WriteLine(a); // Outputs: 10 Console.WriteLine(b); // Outputs: 20 ref is typically used when a method needs to modify an existing variable, while out is used when a method needs to return multiple values or initialize values that were not provided by the caller. ref is typically used when a method needs to modify an existing variable, while out is used when a method needs to return multiple values or initialize values that were not provided by the caller. 4. Async and Await: Improving Application Performance In .NET, asynchronous programming is essential for writing efficient applications that perform well under load. The async and await keywords simplify working with asynchronous operations. async methods allow you to perform tasks asynchronously. Mark a method with the async keyword to enable the use of await inside it. async methods allow you to perform tasks asynchronously. Mark a method with the async keyword to enable the use of await inside it. async public async Task<string> FetchDataAsync() { await Task.Delay(1000); // Simulates an asynchronous operation return "Data fetched"; } public async Task<string> FetchDataAsync() { await Task.Delay(1000); // Simulates an asynchronous operation return "Data fetched"; } await helps application UI by not blocking the main thread. await helps application UI by not blocking the main thread. await public async Task ShowDataAsync() { string data = await FetchDataAsync(); Console.WriteLine(data); } public async Task ShowDataAsync() { string data = await FetchDataAsync(); Console.WriteLine(data); } If you want improve performance of your application use async and await effectively and at the same time keeping application UI responsive. If you want improve performance of your application use async and await effectively and at the same time keeping application UI responsive. 5. Exception Handling in .NET Core Applications Handling exceptions gracefully is crucial for maintaining robust and user-friendly applications. .NET Core provides various mechanisms for exception handling. Local exception handling: Use try-catch blocks to catch and handle exceptions. Local exception handling: Use try-catch blocks to catch and handle exceptions. Local exception handling: try { int result = 10 / 0; // This will throw a DivideByZeroException } catch (DivideByZeroException ex) { Console.WriteLine("An error occurred: " + ex.Message); } try { int result = 10 / 0; // This will throw a DivideByZeroException } catch (DivideByZeroException ex) { Console.WriteLine("An error occurred: " + ex.Message); } Global exception handling in ASP.NET Core can be managed using middleware. Catch all types of exceptions in a common place which helps developers to manage user-friendly/common error messages for users. Global exception handling in ASP.NET Core can be managed using middleware. Catch all types of exceptions in a common place which helps developers to manage user-friendly/common error messages for users. Global exception handling ASP.NET public void Configure(IApplicationBuilder app) { app.UseExceptionHandler("/Home/Error"); } public void Configure(IApplicationBuilder app) { app.UseExceptionHandler("/Home/Error"); } Global exception handling middleware provides a common place to handle all application errors and exceptions. It ensures application consistently handles responses. Global exception handling middleware provides a common place to handle all application errors and exceptions. It ensures application consistently handles responses. 6. The Role of appsettings.json ASP.NET Core ASP.NET The appsettings.json file is used for managing application credentials, such as configuration strings and other application-specific keys. The configuration settings can be divided as per environments too Example appsettings.json file: Example appsettings.json file: Example appsettings.json file: { "ConnectionStrings": { "DefaultConnection": "Server=myServerAddress;Database=myDataBase;User Id=myUsername;Password=myPassword;" }, "Logging": { "LogLevel": { "Default": "Warning" } } } { "ConnectionStrings": { "DefaultConnection": "Server=myServerAddress;Database=myDataBase;User Id=myUsername;Password=myPassword;" }, "Logging": { "LogLevel": { "Default": "Warning" } } } Accessing configuration values in your application is straightforward using the built-in configuration system. Accessing configuration values in your application is straightforward using the built-in configuration system. Accessing configuration values public class MyService { private readonly string _connectionString; public MyService(IConfiguration configuration) { _connectionString = configuration.GetConnectionString("DefaultConnection"); } } public class MyService { private readonly string _connectionString; public MyService(IConfiguration configuration) { _connectionString = configuration.GetConnectionString("DefaultConnection"); } } The appsettings.json file allows for easily fetch configuration settings, needs to handled efficiently. The appsettings.json file allows for easily fetch configuration settings, needs to handled efficiently. 7. Understanding Task vs. Thread in C# Both Task and Thread are used for concurrent programming in C#, but they serve different purposes. Thread represents a single path of execution and is a lower-level construct. It provides more control over the execution but requires manual management. Thread represents a single path of execution and is a lower-level construct. It provides more control over the execution but requires manual management. Thread Thread thread = new Thread(() => { Console.WriteLine("Running on a new thread"); }); thread.Start(); Thread thread = new Thread(() => { Console.WriteLine("Running on a new thread"); }); thread.Start(); Task provides an abstract functionality to implement async operations and is used along with async/await. Task provides an abstract functionality to implement async operations and is used along with async/await. Task Task.Run(() => { Console.WriteLine("Running asynchronously"); }); Task.Run(() => { Console.WriteLine("Running asynchronously"); }); Tasks simplify the management of asynchronous operations and are often the preferred choice for modern C# development. Tasks simplify the management of asynchronous operations and are often the preferred choice for modern C# development. Access the complete C# .Net Interview Series Access the complete C# .Net Interview Series C# .Net Interview Series So, how did you do? If you know the concept with confidence and understand the code examples, you’re likely well-versed in .NET. Let’s keep the conversation going and help each other grow as .NET professionals. Happy coding!