Showing 50 question(s)
Answer:
Value types (int, float, struct) store data directly in memory and are allocated on the stack. Reference types (class, interface, delegate) store a reference to the data, which is allocated on the heap. Value types are copied when assigned, while reference types are not.
Code Example:
// Value Type
int a = 5;
int b = a;
b = 10;
Console.WriteLine(a); // Output: 5
// Reference Type
class Person { public int Age { get; set; } }
Person p1 = new Person { Age = 25 };
Person p2 = p1;
p2.Age = 30;
Console.WriteLine(p1.Age); // Output: 30Answer:
Nullable types allow value types to represent undefined or null values. They are declared using the ? operator (e.g., int?). Nullable types have a HasValue property and a Value property to check if a value is assigned and retrieve it safely.
Code Example:
// Nullable Type
int? number = null;
if (number.HasValue)
{
Console.WriteLine(number.Value);
}
// Using GetValueOrDefault
int result = number.GetValueOrDefault(0);
// Null coalescing
int value = number ?? -1;Answer:
Polymorphism allows objects to take multiple forms. In C#, it is achieved through method overriding (virtual/override keywords), method overloading, and interface implementation. This enables code flexibility and reusability.
Code Example:
// Method Overloading
public void Print(int value) { Console.WriteLine(value); }
public void Print(string value) { Console.WriteLine(value); }
// Method Overriding
public class Animal { public virtual void Sound() => Console.WriteLine("Generic sound"); }
public class Dog : Animal { public override void Sound() => Console.WriteLine("Woof"); }
Animal dog = new Dog();
dog.Sound(); // Output: WoofAnswer:
Encapsulation hides internal implementation details and only exposes what is necessary. In C#, it is achieved using access modifiers (private, public, protected). Example: A class with a private field and public property getter/setter.
Code Example:
public class BankAccount
{
private decimal balance;
public decimal Balance
{
get { return balance; }
private set { balance = value; }
}
public void Deposit(decimal amount) => balance += amount;
}Answer:
LINQ (Language Integrated Query) provides a unified way to query different data sources like arrays, lists, databases, and XML. Advantages: type-safe queries, IntelliSense support, deferred execution, and cleaner syntax compared to loops.
Code Example:
var numbers = new[] { 1, 2, 3, 4, 5 };
// LINQ Query
var evens = numbers.Where(n => n % 2 == 0)
.Select(n => n * n)
.OrderBy(n => n);
// Equivalent to multiple loops but cleaner
foreach (var num in evens)
Console.WriteLine(num);Answer:
IEnumerable works with in-memory collections (LINQ to Objects), while IQueryable works with out-of-memory data sources (databases). IQueryable uses expression trees for query translation, enabling server-side filtering, whereas IEnumerable uses delegates.
Code Example:
// IEnumerable - LINQ to Objects
IEnumerable<int> numbers = new[] { 1, 2, 3, 4, 5 };
var result1 = numbers.Where(n => n > 2); // Client-side filtering
// IQueryable - LINQ to SQL
IQueryable<Product> products = dbContext.Products;
var result2 = products.Where(p => p.Price > 100); // Server-side filteringAnswer:
Task represents an asynchronous operation that may return a value. async/await is syntactic sugar built on top of Tasks. async marks a method as asynchronous, and await pauses execution until the Task completes, making asynchronous code read like synchronous code.
Code Example:
// Using Task
public Task FetchDataAsync()
{
return Task.Delay(1000);
}
// Using async/await
public async Task FetchDataAsyncWithAwait()
{
await Task.Delay(1000);
}
// Calling
await FetchDataAsyncWithAwait();Answer:
Deadlock in async occurs when waiting synchronously for an async operation. Avoid by: always using await instead of .Result or .Wait(), using ConfigureAwait(false) in libraries, or running on thread pool threads.
Code Example:
// WRONG - Causes Deadlock
var result = FetchDataAsync().Result;
// CORRECT - Use await
var result = await FetchDataAsync();
// In libraries, use ConfigureAwait
public async Task<string> GetDataAsync()
{
var data = await httpClient.GetAsync(url);
return await data.Content.ReadAsStringAsync()
.ConfigureAwait(false);
}Answer:
DbContext is the main class for database operations and manages the connection. DbSet<T> represents a table in the database. DbContext contains DbSet properties for each entity type, and it tracks changes and handles CRUD operations.
Code Example:
public class ApplicationDbContext : DbContext
{
// DbSet represents table
public DbSet<User> Users { get; set; }
public DbSet<Order> Orders { get; set; }
// DbContext manages the connection and changes
protected override void OnConfiguring(DbContextOptionsBuilder options)
{
options.UseSqlServer("connection_string");
}
}Answer:
Lazy loading: Related entities are loaded on demand. Eager loading: Related entities are loaded immediately using Include(). Explicit loading: Related entities are explicitly loaded after the main entity using Load() or LoadAsync().
Code Example:
// Lazy Loading
var user = dbContext.Users.FirstOrDefault(); // Orders not loaded yet
var orders = user.Orders; // Loaded on access
// Eager Loading
var user = dbContext.Users.Include(u => u.Orders)
.FirstOrDefault(); // Orders loaded immediately
// Explicit Loading
var user = dbContext.Users.FirstOrDefault();
dbContext.Entry(user).Collection(u => u.Orders).Load();Answer:
DI promotes loose coupling, improves testability, enhances maintainability, and makes code more flexible. It simplifies object creation and management through automatic dependency resolution.
Code Example:
// Without DI (Tightly Coupled)
public class OrderService
{
private readonly Database db = new Database();
}
// With DI (Loosely Coupled)
public class OrderService
{
private readonly IDatabase db;
public OrderService(IDatabase db) => this.db = db;
}
// Registration
services.AddScoped<IDatabase, Database>();Answer:
Singleton ensures a class has only one instance and provides a global access point. Use it for database connections, logging, or configuration management. In .NET, implement using private constructors and static instance.
Code Example:
public class Singleton
{
private static Singleton instance;
private Singleton() { }
public static Singleton GetInstance()
{
if (instance == null)
instance = new Singleton();
return instance;
}
}
// Thread-safe version
public class Singleton
{
private static readonly Lazy<Singleton> lazy =
new Lazy<Singleton>(() => new Singleton());
public static Singleton Instance => lazy.Value;
}Answer:
The Factory pattern creates objects without specifying exact classes. Benefits: decouples client code from concrete classes, centralizes object creation logic, and makes it easier to extend or modify object creation. Common in frameworks for plugin architecture.
Code Example:
public interface ILogger { void Log(string message); }
public class ConsoleLogger : ILogger { public void Log(string msg) => Console.WriteLine(msg); }
public class FileLogger : ILogger { public void Log(string msg) { /* write to file */ } }
public class LoggerFactory
{
public static ILogger CreateLogger(string type) => type switch
{
"console" => new ConsoleLogger(),
"file" => new FileLogger(),
_ => throw new ArgumentException("Unknown logger type")
};
}Answer:
try-catch-finally is for exception handling with cleanup code. using statement is specifically for IDisposable objects, automatically calling Dispose() even if exceptions occur. using is cleaner for resource management while try-finally is more flexible.
Code Example:
// try-catch-finally
try { /* code */ }
catch (Exception ex) { /* handle */ }
finally { /* cleanup */ }
// using statement
using (var connection = new SqlConnection(connectionString))
{
connection.Open();
} // Dispose() called automatically
// C# 8+ using declaration
using SqlConnection connection = new SqlConnection(connectionString);
// Disposed at end of methodAnswer:
Custom exceptions inherit from Exception class to handle domain-specific errors. Create by extending Exception and optionally override constructors to pass error details. Use meaningful names and include relevant context to help debugging.
Code Example:
public class InsufficientBalanceException : Exception
{
public decimal Required { get; }
public decimal Current { get; }
public InsufficientBalanceException(decimal required, decimal current)
: base($"Required: {required}, Current: {current}")
{
Required = required;
Current = current;
}
}
// Usage
throw new InsufficientBalanceException(100, 50);Answer:
List<T> is a concrete, mutable collection with indexing. IEnumerable<T> is read-only, iteration-only interface. ICollection<T> adds Count, Add, Remove methods but still read-only in some contexts. Use List<T> for storage, IEnumerable<T> for LINQ chains.
Code Example:
// List<T> - Mutable with indexing
List<int> list = new List<int> { 1, 2, 3 };
list.Add(4);
Console.WriteLine(list[0]); // 1
// IEnumerable<T> - Read-only iteration
IEnumerable<int> enumerable = list.Where(x => x > 2);
// ICollection<T> - Add, Remove, Count
ICollection<int> collection = list;
collection.Add(5);
Console.WriteLine(collection.Count); // 5Answer:
Dictionary<K,V> is generic, type-safe, and faster. Hashtable is non-generic, slower, and stores objects. Always prefer Dictionary<K,V> in modern C# as it offers better performance and type safety. Hashtable is legacy.
Code Example:
// Dictionary<K,V> - Preferred
Dictionary<string, int> dict = new Dictionary<string, int>();
dict["age"] = 25;
int age = dict["age"]; // Type-safe
// Hashtable - Legacy, avoid
Hashtable table = new Hashtable();
table["age"] = 25;
object age = table["age"]; // Not type-safeAnswer:
string is immutable; each modification creates a new object causing memory waste. StringBuilder is mutable and designed for multiple modifications. Use StringBuilder for loops or concatenations, string for simple concatenations.
Code Example:
// String concatenation - Inefficient
string result = "";
for (int i = 0; i < 1000; i++)
result += i; // Creates 1000 new strings
// StringBuilder - Efficient
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 1000; i++)
sb.Append(i);
string result = sb.ToString();Answer:
Reflection allows inspection of assemblies, types, and members at runtime using System.Reflection. Use cases: dynamic property/method invocation, serialization, ORM frameworks. Trade-off: powerful but slower than direct code.
Code Example:
Type type = typeof(MyClass);
PropertyInfo[] properties = type.GetProperties();
MethodInfo[] methods = type.GetMethods();
// Invoke method dynamically
object instance = Activator.CreateInstance(type);
MethodInfo method = type.GetMethod("MyMethod");
method.Invoke(instance, new object[] { });
// Get property value
PropertyInfo prop = type.GetProperty("Name");
object value = prop.GetValue(instance);Answer:
Delegates are type-safe function pointers. Events are a wrapper around delegates for publish-subscribe pattern. Events restrict external code from reassigning or clearing subscribers. Use events for external objects, delegates for internal callbacks.
Code Example:
// Delegate - Type-safe function pointer
public delegate void NotifyDelegate(string message);
// Event - Wrapper around delegate
public class Publisher
{
public event NotifyDelegate OnNotify;
public void Notify(string msg) => OnNotify?.Invoke(msg);
}
// Usage
Publisher pub = new Publisher();
pub.OnNotify += (msg) => Console.WriteLine(msg);
pub.Notify("Hello"); // External code can't do: pub.OnNotify = null;Answer:
Action<T> takes parameters but returns void. Func<T, TResult> takes parameters and returns a value. Delegate is the base type. Use Action for methods with no return, Func for methods with return values. They are more concise than custom delegates.
Code Example:
// Action - No return value
Action<string> print = (msg) => Console.WriteLine(msg);
print("Hello");
// Func - Returns value
Func<int, int, int> add = (a, b) => a + b;
int result = add(5, 3); // 8
// Delegate - Base type
public delegate int Calculate(int a, int b);
Calculate calc = (a, b) => a * b;
int product = calc(5, 3); // 15Answer:
Attributes are metadata annotations that provide information about code without affecting functionality. Used with reflection for frameworks like Entity Framework (Table, Column), Serialization (Serializable), and Validation (Required, Range).
Code Example:
[Serializable]
public class User
{
[Required(ErrorMessage = "Name is required")]
public string Name { get; set; }
[Range(1, 120, ErrorMessage = "Invalid age")]
public int Age { get; set; }
}
// Custom attribute
[AttributeUsage(AttributeTargets.Class)]
public class ApiControllerAttribute : Attribute { }
[ApiController]
public class UserController { }Answer:
sealed class prevents inheritance; abstract class requires inheritance. sealed is for final classes that shouldn't be extended. abstract is for base classes that define structure. Both are useful for different scenarios in OOP.
Code Example:
// abstract - Must be inherited
public abstract class Animal
{
public abstract void Sound();
public virtual void Move() { }
}
// sealed - Cannot be inherited
public sealed class FinalClass { }
// This will not compile
// public class DerivedFromFinal : FinalClass { }Answer:
Generic constraints restrict type parameters. Examples: where T : class (reference type), where T : struct (value type), where T : IComparable (implements interface), where T : BaseClass (inherits class). Improve type safety and allow using type-specific members.
Code Example:
// where T : class - Reference types only
public class GenericClass<T> where T : class { }
// where T : struct - Value types only
public class ValueClass<T> where T : struct { }
// where T : IComparable - Must implement interface
public class ComparableClass<T> where T : IComparable { }
// where T : new() - Must have parameterless constructor
public class ConstructorClass<T> where T : new()
{
public T Create() => new T();
}Answer:
Covariance allows assigning a more derived type. Contravariance allows assigning a less derived type. Declared with out (covariant) and in (contravariant) keywords. Important for IEnumerable<T> (covariant) and Action<T> (contravariant).
Code Example:
// Covariance (out)
IEnumerable<string> strings = new List<string> { "a", "b" };
IEnumerable<object> objects = strings; // OK - covariant
// Contravariance (in)
Action<object> actionObj = (obj) => Console.WriteLine(obj);
Action<string> actionStr = actionObj; // OK - contravariant
actionStr("hello");
// Custom example
public interface IProducer<out T> { T Produce(); }
public interface IConsumer<in T> { void Consume(T item); }Answer:
Middleware is software that is assembled into the application pipeline to handle requests and responses. Each middleware component can perform work before and after the next middleware in the pipeline.
Code Example:
app.UseAuthentication();
app.UseAuthorization();
app.MapControllers();Answer:
ASP.NET Core has a built-in IoC container that automatically injects services into controllers and other classes. Services can be registered as Singleton, Scoped, or Transient.
Code Example:
builder.Services.AddScoped<IUserService, UserService>();
public class UserController
{
private readonly IUserService _service;
public UserController(IUserService service)
{
_service = service;
}
}Answer:
Singleton creates one instance for the application lifetime. Scoped creates one instance per HTTP request. Transient creates a new instance every time it is requested.
Code Example:
services.AddSingleton<ILogService, LogService>();
services.AddScoped<IUserService, UserService>();
services.AddTransient<IEmailService, EmailService>();Answer:
REST is an architectural style for designing web APIs. It uses HTTP methods like GET, POST, PUT, PATCH, and DELETE to perform CRUD operations on resources.
Code Example:
[HttpGet]
public IActionResult GetUsers()
{
return Ok(users);
}Answer:
PUT replaces the entire resource, while PATCH updates only specific fields.
Code Example:
PUT /users/1
PATCH /users/1Answer:
JWT (JSON Web Token) is a compact token containing user claims. After login, the server generates a signed token which clients send with every request for authentication.
Code Example:
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...Answer:
Authentication verifies who the user is. Authorization determines what the authenticated user is allowed to access.
Code Example:
[Authorize(Roles="Admin")]
public IActionResult Delete()
{
return Ok();
}Answer:
Migrations manage database schema changes by generating SQL scripts based on model changes.
Code Example:
Add-Migration InitialCreate
Update-DatabaseAnswer:
AsNoTracking() improves read performance by preventing Entity Framework from tracking retrieved entities.
Code Example:
var users = await context.Users
.AsNoTracking()
.ToListAsync();Answer:
Optimistic concurrency assumes conflicts are rare and detects updates using a concurrency token such as RowVersion.
Code Example:
public byte[] RowVersion { get; set; }Answer:
In-memory caching stores frequently accessed data in application memory to improve performance.
Code Example:
services.AddMemoryCache();
_cache.Set("users", users);Answer:
Distributed caching stores cache outside the application, such as Redis, allowing multiple servers to share cached data.
Code Example:
services.AddStackExchangeRedisCache(options =>
{
options.Configuration = "localhost";
});Answer:
Use async programming, caching, response compression, AsNoTracking(), pagination, connection pooling, and avoid unnecessary allocations.
Code Example:
app.UseResponseCompression();Answer:
ASP.NET Core provides ILogger<T> for structured logging and supports providers like Console, Debug, EventSource, Serilog, and NLog.
Code Example:
private readonly ILogger<HomeController> logger;
logger.LogInformation("Application started");Answer:
Configuration comes from appsettings.json, environment variables, command-line arguments, and secrets. IConfiguration provides access to configuration values.
Code Example:
string conn = configuration.GetConnectionString("Default");Answer:
SOLID stands for Single Responsibility, Open/Closed, Liskov Substitution, Interface Segregation, and Dependency Inversion. These principles improve maintainability and flexibility.
Code Example:
// SRP Example
public class InvoiceService
{
public void Save() {}
}Answer:
Repository abstracts data access logic and provides a clean separation between business logic and persistence.
Code Example:
public interface IUserRepository
{
Task<User> GetByIdAsync(int id);
}Answer:
Unit testing verifies individual methods or components in isolation using frameworks like xUnit, NUnit, or MSTest.
Code Example:
[Fact]
public void Add_ShouldReturnFive()
{
Assert.Equal(5, 2 + 3);
}Answer:
Mocking replaces real dependencies with fake implementations to isolate unit tests.
Code Example:
var mock = new Mock<IUserService>();
mock.Setup(x => x.GetName()).Returns("John");Answer:
Microservices are independently deployable services that communicate over HTTP, gRPC, or messaging systems.
Code Example:
GET /api/ordersAnswer:
Status codes indicate request outcomes. Common codes include 200 OK, 201 Created, 400 Bad Request, 401 Unauthorized, 403 Forbidden, 404 Not Found, and 500 Internal Server Error.
Code Example:
return NotFound();
return Ok(data);
return BadRequest();Answer:
Serialization converts objects into JSON for transmission or storage. Deserialization converts JSON back into .NET objects.
Code Example:
string json = JsonSerializer.Serialize(user);
User u = JsonSerializer.Deserialize<User>(json);Answer:
Cross-Origin Resource Sharing allows or blocks requests from different origins based on configured policies.
Code Example:
builder.Services.AddCors();
app.UseCors(policy =>
policy.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader());Answer:
The Garbage Collector automatically reclaims memory occupied by objects that are no longer referenced. It uses generations (Gen 0, Gen 1, Gen 2) to optimize memory management.
Code Example:
GC.Collect(); // Generally avoid calling manuallyAnswer:
IActionResult allows multiple response types. ActionResult<T> returns either a strongly typed object or an HTTP result. Returning a specific type is best when only one response type is expected.
Code Example:
public ActionResult<User> Get(int id)
{
var user = repo.Get(id);
if(user == null)
return NotFound();
return user;
}