INTERVIEW ANSWERS — PART 1 (TOPICS) C# · OOPS · .NET Core · Entity Framework · SQL Server

                                               SECTION 1: C# FUNDAMENTALS

Q1. What is the difference between Abstract class vs Interface?

Abstract Class: can have implementation (concrete methods), fields, constructors, access modifiers. Supports single inheritance only. Used for IS-A relationships among related classes. 

Interface: pure contract — method signatures (before C# 8), no fields, no constructors, all public by default. Multiple interfaces allowed. Used for IS-WHAT (capability) relationships.

Code:
// Abstract class

public abstract class Shape {
    public string Color = "Red"; // field allowed
    public abstract double Area(); // must override
    public virtual void Print() => // can override
        Console.WriteLine($"Color: {Color}");
}
// Interface

public interface IDrawable { void Draw(); }
public interface IResizable { void Resize(int factor); }
// Class inherits ONE base + MULTIPLE interfaces
public class Circle : Shape, IDrawable, IResizable {
    public double Radius { get; set; }
    public override double Area() => Math.PI * Radius * Radius;
    public void Draw() => Console.WriteLine("Drawing circle");
    public void Resize(int factor) => Radius *= factor;
}

// Rule of thumb:

// Abstract = shared code + state among related types
// Interface = contract / capability for unrelated types

Q2. What is Polymorphism? Explain with examples.
Polymorphism = 'many forms'. Two types: 1. Compile-time (static) — method overloading: same name, different parameters. 2. Runtime (dynamic) — method overriding via virtual/override: child decides behavior at runtime.

Code:

// Compile-time polymorphism (overloading)

public class Logger {
    public void Log(string msg) => Console.WriteLine(msg);
    public void Log(string msg, int level) => Console.WriteLine($"[{level}] {msg}");
    public void Log(Exception ex) => Console.WriteLine(ex.Message);
}

// Runtime polymorphism (overriding)

public abstract class Animal {
    public virtual void Speak() => Console.WriteLine("...");
}
public class Dog : Animal {
    public override void Speak() => Console.WriteLine("Woof");
}
public class Cat : Animal {
    public override void Speak() => Console.WriteLine("Meow");
}

// Same base reference — different behavior at runtime

Animal[] animals = { new Dog(), new Cat() };
foreach (var a in animals) a.Speak(); // Woof Meow

Q3. Explain Encapsulation vs Abstraction.

Encapsulation: bundling data + methods, hiding internal state using access modifiers (private/protected). Controls how data is read/written.

Abstraction: hiding implementation complexity, exposing only what is needed. 'What to do' not 'how to do it'.

Code:

// Encapsulation — private field, public property

public class BankAccount {
    private decimal _balance; // hidden
    public decimal Balance => _balance; // read-only view
    public void Deposit(decimal amount) {
        if (amount <= 0) throw new ArgumentException("Positive only");
        _balance += amount;
    }
    public bool Withdraw(decimal amount) {
        if (amount > _balance) return false;
        _balance -= amount;
        return true;
    }
}

// Abstraction — hide HOW payment works

public abstract class Payment {
    public abstract void Process(decimal amount); // what
}
public class CreditCard : Payment {
    public override void Process(decimal amount) {
        ValidateCard(); ChargeGateway(amount); SendReceipt(); // how (hidden)
    }
    private void ValidateCard() { /* ... */ }
    private void ChargeGateway(decimal a) { /* ... */ }
    private void SendReceipt() { /* ... */ }
}

Q4. What is the difference between var vs dynamic in C#?
var: type inferred at COMPILE time — still fully type-safe, zero runtime overhead. 
dynamic: type resolved at RUNTIME via reflection — bypasses compile-time checks, performance overhead.

Code:

var x = 42; // int at compile time — intellisense works
var s = "hello"; // string — cannot do s = 10 later (compile error)

dynamic d = 42;
d = "now a string"; // OK at runtime — no compile error
d = new List<int>(); // also OK

// Use var: always (clean, type-safe)
// Use dynamic: COM interop, JSON deserialization, ExpandoObject

dynamic expando = new System.Dynamic.ExpandoObject();
expando.Name = "Vamshi"; // property created at runtime
Console.WriteLine(expando.Name);

Q5. Explain the static keyword and static class in C#.
static member: belongs to the TYPE, not an instance. Shared across all instances. Accessed via class name. 
static class: cannot be instantiated, all members must be static. Used for utility / helper classes.

Code:

// Static member

public class Counter {
    public static int Total = 0; // shared
    public int Id;
    public Counter() { Id = ++Total; }
}
var c1 = new Counter(); // Total = 1
var c2 = new Counter(); // Total = 2
Console.WriteLine(Counter.Total); // 2

// Static class — utility

public static class MathUtils {
    public static double Square(double n) => n * n;
    public static double CircleArea(double r) => Math.PI * r * r;
}
Console.WriteLine(MathUtils.Square(5)); // 25
Console.WriteLine(MathUtils.CircleArea(3)); // 28.27

Q6. Difference between Const vs Readonly.
const: compile-time constant, implicitly static, must be a literal, cannot be changed ever. 
readonly: runtime constant, can be set in constructor, supports complex types.

Code:

public class Config {
    public const int MaxRetries = 3; // compile-time, literal only
    public const string AppName = "MyApp";
    public readonly DateTime StartedAt; // runtime
    public readonly List<string> AllowedIPs; // complex type OK
    public Config() {
        StartedAt = DateTime.UtcNow; // set in constructor
        AllowedIPs = new List<string> { "127.0.0.1" };
    }
}
// Config.MaxRetries = 5; // ERROR — const
// cfg.StartedAt = DateTime.Now; // ERROR — readonly after ctor

Q7. Explain ref vs out keywords.
ref: pass by reference; caller MUST initialise first; method can read AND write. 
out: pass by reference for output; caller need NOT initialise; method MUST assign before return.

Code:

// ref — caller initialises, method reads and writes
void Double(ref int n) => n *= 2;
int num = 5;
Double(ref num);
Console.WriteLine(num); // 10

// out — caller does not initialise; method must write
bool TryParse(string s, out int result) {
    if (int.TryParse(s, out result)) return true;
    result = 0; return false;
}
if (TryParse("42", out int val))
    Console.WriteLine(val); // 42

// Swap using ref
void Swap(ref int a, ref int b) { int t = a; a = b; b = t; }
int x = 1, y = 2;
Swap(ref x, ref y);
Console.WriteLine($"{x},{y}"); // 2,1

Q8. What is Sealed class in C#?
A sealed class cannot be inherited. Prevents further derivation — used for security, performance, or design correctness. Also applicable to methods inside unsealed classes.

Code:

public sealed class Singleton {
    private static Singleton _i;
    private Singleton() { }
    public static Singleton Instance => _i ??= new Singleton();
}
// class SubSingleton : Singleton { } // ERROR — sealed

// Sealed override — allows overriding but prevents further overrides
public class Base { public virtual void Run() => Console.WriteLine("Base"); }
public class Child : Base { public sealed override void Run() => Console.WriteLine("Child"); }
public class GChild : Child { /* public override void Run() {} */ // ERROR — sealed }

Q9. What is method signature?
A method signature is its unique identity: METHOD NAME + PARAMETER TYPES (count, order, types). Return type is NOT part of the signature. Overloading is based on signature.

Code:

public class Calc {
    // Different signatures — legal overloads
    public int Add(int a, int b) => a + b; // (int,int)
    public double Add(double a, double b) => a + b; // (double,double)
    public int Add(int a, int b, int c) => a + b + c; // (int,int,int)

    // Same signature — ILLEGAL even if return type differs
    // public string Add(int a, int b) => ""; // COMPILE ERROR
}

Q10. What is the Order of constructor execution?
Static constructors run once when the type is first used: base static → derived static. Then instance constructors: base instance → derived instance (base runs before child).

Code:

class Animal {
    static Animal() => Console.WriteLine("1. Animal static ctor");
    public Animal() => Console.WriteLine("3. Animal instance ctor");
}
class Dog : Animal {
    static Dog() => Console.WriteLine("2. Dog static ctor");
    public Dog() => Console.WriteLine("4. Dog instance ctor");
}
var d = new Dog();
// Output:
// 1. Animal static ctor
// 2. Dog static ctor
// 3. Animal instance ctor
// 4. Dog instance ctor

Q11. What is destructor and how many can be there in a class?
A destructor (finalizer ~ClassName) is called by GC before object memory is reclaimed. Only ONE allowed per class. Non-deterministic — you cannot predict when it runs. Prefer IDisposable pattern.

Code:

public class FileWrapper {
    ~FileWrapper() { // only one allowed
        Console.WriteLine("Finalizer called by GC");
    }
}
// Preferred: IDisposable (deterministic cleanup)
public class DbConn : IDisposable {
    private SqlConnection _conn;
    public DbConn(string cs) => _conn = new SqlConnection(cs);
    public void Dispose() { _conn?.Dispose(); GC.SuppressFinalize(this); }
    ~DbConn() => Dispose(); // safety net
}
using var db = new DbConn("..."); // Dispose called automatically

Q12. Why do you need a destructor when GC is there?
GC manages MANAGED memory automatically. But unmanaged resources (file handles, native memory, OS handles, COM objects) are NOT tracked by GC. A destructor/finalizer provides a safety net to release unmanaged resources if Dispose() was never called.

Code:

// Without destructor — unmanaged handle leaks if user forgets Dispose()

public class NativeResource : IDisposable {
    private IntPtr _handle; // unmanaged
    public NativeResource() => _handle = NativeLib.Open();
    public void Dispose() {
        if (_handle != IntPtr.Zero) {
            NativeLib.Close(_handle);
            _handle = IntPtr.Zero;
        }
        GC.SuppressFinalize(this); // tell GC: finalizer not needed
    }
    ~NativeResource() => Dispose(); // safety net
}

Q13. What happens when constructor is private?
A private constructor prevents external instantiation. Common uses: Singleton pattern, static utility classes, factory methods that control object creation.

Code:

// Singleton — private ctor

public class AppConfig {
    private static readonly AppConfig _instance = new AppConfig();
    private AppConfig() { /* load config */ }
    public static AppConfig Instance => _instance;
    public string Theme { get; set; } = "Dark";
}
// var c = new AppConfig(); // ERROR
var cfg = AppConfig.Instance; // OK

// Factory pattern

public class Temperature {
    private Temperature(double c) => Celsius = c;
    public double Celsius { get; }
    public static Temperature FromCelsius(double c) => new Temperature(c);
    public static Temperature FromFahrenheit(double f) => new Temperature((f - 32) / 1.8);
}
var t = Temperature.FromFahrenheit(100); // 37.78 C

Q14. If an Abstract class has a concrete method, can its child have the same method name and modify it?
Yes — using the override keyword (if virtual/abstract) or the new keyword (method hiding). Override is polymorphic; new hides without polymorphism.

Code:

public abstract class Vehicle {
    public abstract void Start(); // must override
    public virtual void Stop() => Console.WriteLine("Vehicle stop"); // can override
    public void Refuel() => Console.WriteLine("Vehicle refuel"); // hide with new
}
public class Car : Vehicle {
    public override void Start() => Console.WriteLine("Car start"); // polymorphic
    public override void Stop() => Console.WriteLine("Car stop"); // polymorphic
    public new void Refuel() => Console.WriteLine("Car refuel"); // hides — NOT polymorphic
}
Vehicle v = new Car();
v.Start(); // Car start (override — runtime dispatch)
v.Stop(); // Car stop (override)
v.Refuel(); // Vehicle refuel (new — compile-time, Vehicle version called)

Q15. Abstract vs Static class
Abstract: blueprint for inheritance; can be instantiated only via subclass; supports polymorphism; can have instance & static members. 
Static: cannot be instantiated at all; all members must be static; cannot be inherited; used for utility functions.

Code:

// Abstract — designed for inheritance

public abstract class Report {
    public string Title { get; set; }
    public abstract void Generate(); // subclasses implement
    public void Save() => File.WriteAllText(Title + ".txt", "...");
}

// Static — utility, no instantiation

public static class StringHelper {
    public static string ToPascalCase(string s) =>
        string.Join("", s.Split(' ').Select(w =>
            char.ToUpper(w[0]) + w[1..].ToLower()));
}
// new Report() — ERROR (abstract)
// new StringHelper() — ERROR (static)
// Report r = new Invoice(); — OK (concrete child)
Console.WriteLine(StringHelper.ToPascalCase("hello world")); // HelloWorld

Q16. Why does abstract class have constructors?
Abstract classes can have constructors to initialise shared state (fields) that all subclasses need. The constructor is called via base() from the derived class. It cannot be called directly because the class cannot be instantiated directly.

Code:

public abstract class Animal {
    public string Name { get; }
    public int Age { get; }
    protected Animal(string name, int age) { // base ctor initialises common state
        Name = name;
        Age = age;
    }
    public abstract void Speak();
}
public class Dog : Animal {
    public Dog(string name, int age) : base(name, age) { } // calls base ctor
    public override void Speak() => Console.WriteLine($"{Name} says Woof!");
}
var d = new Dog("Rex", 3);
d.Speak(); // Rex says Woof!

Q17. When to use abstract vs interface — real-time example in C#
Use abstract class when related types share code/state (e.g. all reports share a header). Use interface when unrelated types share a capability (e.g. anything that can be serialised).

Code:

// Abstract class — shared code across related types

public abstract class BaseRepository<T> {
    protected readonly DbContext Db;
    public BaseRepository(DbContext db) => Db = db; // shared state
    public T? GetById(int id) => Db.Set<T>().Find(id); // shared impl
    public abstract IEnumerable<T> GetAll(); // each must implement
}

// Interface — unrelated types share capability

public interface IExportable {
    byte[] ExportToPdf();
    byte[] ExportToCsv();
}

// Report uses both: inherits code from abstract, declares capability via interface

public class SalesReport : BaseRepository<Sale>, IExportable {
    public SalesReport(DbContext db) : base(db) { }
    public override IEnumerable<Sale> GetAll() => Db.Sales.ToList();
    public byte[] ExportToPdf() => /* generate PDF */ Array.Empty<byte>();
    public byte[] ExportToCsv() => /* generate CSV */ Array.Empty<byte>();
}

Q18. Implicit and Explicit Interface
Implicit: interface members are public on the class — callable without casting. Explicit: member is only accessible via the interface type — useful when a class implements two interfaces with the same method name, or to hide implementation details.

Code:

public interface IGreet { void Hello(); }
public interface IFarewell { void Hello(); } // same name!
public class Greeter : IGreet, IFarewell {
    void IGreet.Hello() => Console.WriteLine("Hi!"); // explicit
    void IFarewell.Hello() => Console.WriteLine("Bye!"); // explicit
    public void PublicHello() => Console.WriteLine("Hello!"); // implicit
}
var g = new Greeter();
g.PublicHello(); // Hello!
// g.Hello(); // ERROR — not accessible directly
((IGreet)g).Hello(); // Hi!
((IFarewell)g).Hello(); // Bye!

Q19. What is default interface method and why do we need it?
C# 8+ allows interface methods to have a default implementation. Enables adding new methods to published interfaces without breaking existing implementors (backwards compatibility).

Code:

public interface ILogger {
    void LogInfo(string msg);
    void LogError(string msg);
    // Default implementation — added later; existing classes not forced to implement
    void LogWarning(string msg) =>
        Console.WriteLine($"[WARN] {msg}");
}
public class ConsoleLogger : ILogger {
    public void LogInfo(string msg) => Console.WriteLine($"[INFO] {msg}");
    public void LogError(string msg) => Console.WriteLine($"[ERROR] {msg}");
    // LogWarning not overridden — uses default
}
ILogger log = new ConsoleLogger();
log.LogWarning("Disk 90% full"); // [WARN] Disk 90% full (default)

Q20. Method overriding with example
Method overriding: child class provides its own implementation of a base class virtual/abstract method using the override keyword. The runtime version depends on the actual object type.

Code:

public class Discount {
    public virtual double Calculate(double price) => price * 0.05; // 5%
}
public class FestivalDiscount : Discount {
    public override double Calculate(double price) => price * 0.20; // 20%
}
public class ClearanceDiscount : Discount {
    public override double Calculate(double price) => price * 0.50; // 50%
}
Discount d = new FestivalDiscount();
Console.WriteLine(d.Calculate(1000)); // 200 (runtime dispatch)

Q21. Method hiding with example
Method hiding (using new keyword): the child defines its own method with the same name, but it is NOT polymorphic. When accessed via base reference, the base version is called.

Code:

public class Base { public void Show() => Console.WriteLine("Base"); }
public class Child : Base { public new void Show() => Console.WriteLine("Child"); }

Child c = new Child(); c.Show(); // Child
Base b = new Child(); b.Show(); // Base <- hiding — base version called
// override would print Child here ^
// When to use: rarely — when you need to intentionally shadow a base method

Q22. Is return type considered in method overloading?
NO. Return type is NOT part of the method signature for overload resolution. Two methods that differ only in return type are a compile error. Overloading is based on name + parameter list only.

Code:

public class Parser {
    public int Parse(string s) => int.Parse(s); // sig: Parse(string)
    public double Parse(double d) => d; // sig: Parse(double) — different param
    // public long Parse(string s) => 0; // ERROR — same sig as line 1
}
// These ARE different (parameter types differ)
public int GetId(int code) => code;
public string GetId(string name) => name; // OK — different param type

Q23. Why and when to use method hiding? Real-time scenario
Use method hiding (new) when: (a) you use a library class you cannot modify, (b) the base method is not virtual, and (c) you want a different behaviour for your type without breaking polymorphism of the base.

Code:

// Third-party library — cannot change

public class ThirdPartyLogger {
    public void Log(string msg) => Console.WriteLine($"[OLD] {msg}");
}

// Our class — we want enhanced Log without virtual base

public class EnhancedLogger : ThirdPartyLogger {
    public new void Log(string msg) =>
        Console.WriteLine($"[{DateTime.Now:HH:mm:ss}] {msg}");
}
EnhancedLogger el = new EnhancedLogger();
el.Log("Test"); // [14:30:00] Test (our version)
ThirdPartyLogger tpl = el;
tpl.Log("Test"); // [OLD] Test (base version — hiding, not overriding)

Q24. How to extend a sealed class?
You CANNOT inherit a sealed class. Instead, use: (a) extension methods to add methods without inheritance, or (b) composition — wrap the sealed class inside a new class.

Code:

// Sealed — cannot inherit

public sealed class EmailSender {
    public void Send(string to, string body) => Console.WriteLine($"To: {to}");
}

// Option 1: Extension methods (add new methods, no subclassing)

public static class EmailSenderExt {
    public static void SendWelcome(this EmailSender sender, string email) =>
        sender.Send(email, "Welcome to our platform!");
}
var es = new EmailSender();
es.SendWelcome("vamshi@qa.com"); // works!

// Option 2: Composition

public class EnhancedEmailSender {
    private readonly EmailSender _inner = new EmailSender();
    public void Send(string to, string body) => _inner.Send(to, body);
    public void SendBulk(IEnumerable<string> tos, string body) {
        foreach (var to in tos) _inner.Send(to, body);
    }
}

Q25. What is extension method? Write an example
Extension methods add new methods to existing types without modifying them. Defined in a static class with the this keyword on the first parameter. They appear as instance methods on the type.

Code:

public static class IntExtensions {
    public static bool IsEven(this int n) => n % 2 == 0;
    public static int Squared(this int n) => n * n;
    public static IEnumerable<int> Range(this int from, int to) =>
        Enumerable.Range(from, to - from + 1);
}
Console.WriteLine(4.IsEven()); // True
Console.WriteLine(5.Squared()); // 25
foreach (var n in 1.Range(5)) Console.Write(n + " "); // 1 2 3 4 5

Q26. Purpose of the this keyword in extension methods
The this keyword on the first parameter marks the method as an extension method and tells the compiler which type it extends. Without it the method is just a regular static method. It does NOT mean 'instance of this class'.

Code:

public static class StringExt {
    // 'this string s' — extends the string type
    public static string Truncate(this string s, int maxLen) =>
        s.Length <= maxLen ? s : s[..maxLen] + "...";
}
string title = "Hello World from C# Interview";
Console.WriteLine(title.Truncate(11)); // Hello World...
// Internally the compiler converts:
// title.Truncate(11) => StringExt.Truncate(title, 11)

Q27. Write an extension method example
A practical extension on List<T> to chunk a list into pages.

Code:

public static class ListExtensions {
    public static IEnumerable<List<T>> Paginate<T>(this List<T> source, int pageSize) {
        for (int i = 0; i < source.Count; i += pageSize)
            yield return source.GetRange(i, Math.Min(pageSize, source.Count - i));
    }
}
var employees = Enumerable.Range(1, 10).ToList();
foreach (var page in employees.Paginate(3)) {
    Console.WriteLine(string.Join(", ", page));
}
// 1, 2, 3
// 4, 5, 6
// 7, 8, 9
// 10

Q28. Extension method: given DateTime, return Morning / Afternoon / Evening

Code:

public static class DateTimeExtensions {
    public static string GetTimeOfDay(this DateTime dt) => dt.Hour switch {
        >= 5 and < 12 => "Morning",
        >= 12 and < 17 => "Afternoon",
        >= 17 and < 21 => "Evening",
        _ => "Night"
    };
}
Console.WriteLine(DateTime.Now.GetTimeOfDay());
Console.WriteLine(new DateTime(2025,1,1,9,0,0).GetTimeOfDay()); // Morning
Console.WriteLine(new DateTime(2025,1,1,14,0,0).GetTimeOfDay()); // Afternoon
Console.WriteLine(new DateTime(2025,1,1,19,0,0).GetTimeOfDay()); // Evening

                                          SECTION 2: OOPS & DESIGN CONCEPTS

Q1. Difference between List, Hashtable & Dictionary
List<T>: ordered, index-based, allows duplicates. Use for sequences. Hashtable: non-generic key-value, no type safety, thread-safe (read), legacy. Dictionary<K,V>: generic key-value, type-safe, fast O(1) lookup, not thread-safe by default.

Code:

// List<T>
var list = new List<int> { 3, 1, 2, 1 }; // duplicates OK
list.Add(4); Console.WriteLine(list[0]); // 3 (index-based)
// Dictionary<K,V>
var dict = new Dictionary<string, int> {
    ["Alice"] = 90, ["Bob"] = 85
};
dict["Charlie"] = 92;
Console.WriteLine(dict["Alice"]); // 90
dict.TryGetValue("Dave", out int score); // safe lookup
// Hashtable (legacy — avoid in new code)
var ht = new Hashtable { ["key1"] = "val1" };
Console.WriteLine(ht["key1"]); // val1 (no type-safety, needs cast)

Q2. What is Array & ArrayList?
Array: fixed size, strongly typed, fast. ArrayList: dynamic size, non-generic (stores object), requires boxing/unboxing, legacy. Prefer List<T> over ArrayList.

Code:

// Array — fixed size, typed
int[] nums = new int[3] { 1, 2, 3 };
nums[0] = 10;
// nums[5] = 1; // IndexOutOfRangeException
// ArrayList — dynamic, non-generic (avoid)
var al = new ArrayList { 1, "hello", 3.14 }; // mixed types
al.Add(true);
int n = (int)al[0]; // cast required
// Preferred: List<T> — dynamic + type-safe
var lst = new List<string> { "A", "B" };
lst.Add("C");
Console.WriteLine(lst.Count); // 3

Q3. What is Delegate and where have you used it?
A delegate is a type-safe function pointer — it holds a reference to a method matching a specific signature. Used for callbacks, events, LINQ, and strategy patterns.

Code:

// Delegate declaration
delegate int Operation(int a, int b);
// Usage
Operation add = (a, b) => a + b;
Operation mul = (a, b) => a * b;
Console.WriteLine(add(3, 4)); // 7
Console.WriteLine(mul(3, 4)); // 12
// Built-in delegates
Action<string> log = msg => Console.WriteLine(msg);
Func<int,int,int> sum = (a, b) => a + b;
Predicate<int> isEven = n => n % 2 == 0;
log("Hello"); // Hello
Console.WriteLine(sum(2, 3)); // 5
Console.WriteLine(isEven(4)); // True
// Real use: event handler
button.Click += (s, e) => Console.WriteLine("Clicked");
// Real use: strategy (pass sorting logic)
List<int> nums = new List<int> { 3,1,4,1,5 };
nums.Sort((a, b) => b - a); // descending via delegate

Q4. What is an extension method?
Extension methods add methods to existing types without inheritance. Defined as static methods with this on the first parameter. (See C# Section Q25 for full example.)

Q5. Difference between Ref & Out?
ref: caller must initialise before passing; method can read and write. out: caller need not initialise; method must write before returning.

Code:

void AddTax(ref decimal price) => price *= 1.18m; // reads existing value
decimal p = 100;
AddTax(ref p); Console.WriteLine(p); // 118

bool TryGetUser(int id, out string name) {
    name = id == 1 ? "Vamshi" : null;
    return name != null;
}
if (TryGetUser(1, out string n)) Console.WriteLine(n); // Vamshi

Q6. What is the ASP.Net Page life cycle?
Request -> Init -> Load -> Validate -> Event -> Render -> Unload. (Web Forms). In MVC/Core: Request -> Routing -> Controller selection -> Action execution -> Result -> Response.

Code:

// ASP.NET Web Forms Page Life Cycle (in order):
// 1. PreInit — master page, theme selection
// 2. Init — controls initialised
// 3. InitComplete — initialisation done
// 4. PreLoad
// 5. Load — Page_Load() here
// 6. Control Events — Button_Click etc.
// 7. LoadComplete
// 8. PreRender — last chance to modify controls
// 9. SaveViewState
// 10. Render — HTML generated
// 11. Unload — cleanup
// ASP.NET Core MVC Request Pipeline:
// Request -> Middleware chain -> Routing -> Authorization -> Model binding
// -> Action filters -> Action method -> Result filters -> View/JSON -> Response

Q7. How can we maintain cache / cookie in ASP.NET page?
Cache: IMemoryCache or IDistributedCache (Redis) in .NET Core. Cookie: HttpContext.Response.Cookies.

Code:

// Cache (in-memory)
// Register: services.AddMemoryCache();
public class ProductController : Controller {
    private readonly IMemoryCache _cache;
    public ProductController(IMemoryCache cache) => _cache = cache;
    public IActionResult Index() {
        if (!_cache.TryGetValue("products", out List<string> products)) {
            products = new List<string> { "A", "B", "C" }; // DB call
            _cache.Set("products", products, TimeSpan.FromMinutes(5));
        }
        return Ok(products);
    }
}
// Cookie — read/write
Response.Cookies.Append("UserTheme", "dark", new CookieOptions {
    Expires = DateTimeOffset.UtcNow.AddDays(30),
    HttpOnly = true, Secure = true, SameSite = SameSiteMode.Strict
});
string theme = Request.Cookies["UserTheme"];

Q8. How data can be passed from one controller to another from MVC?
Options: TempData, Session, Query string, Route values, or redirect with route parameters. TempData is most common for single-redirect data.

Code:

// Option 1: TempData (survives one redirect)
public IActionResult CreateOrder() {
    TempData["OrderId"] = 42;
    return RedirectToAction("Confirmation", "Order");
}
// In OrderController:
public IActionResult Confirmation() {
    int orderId = (int)TempData["OrderId"];
    return View(orderId);
}
// Option 2: Query string
return RedirectToAction("Details", "Product", new { id = 5, tab = "reviews" });
// URL: /Product/Details?id=5&tab=reviews
// Option 3: Session
HttpContext.Session.SetString("Cart", JsonSerializer.Serialize(cart));
// In another controller:
var cart = JsonSerializer.Deserialize<Cart>(HttpContext.Session.GetString("Cart"));

Q9. Difference between ViewBag & ViewData?
Both carry data from controller to view for the SAME request. ViewData: dictionary (string key), requires casting. ViewBag: dynamic wrapper around ViewData — no casting but no IntelliSense.

Code:

// Controller
public IActionResult Index() {
    ViewData["Title"] = "Home"; // string key, object value
    ViewBag.Message = "Welcome!"; // dynamic property
    ViewData["Count"] = 42;
    return View();
}
// View (.cshtml)
// @ViewData["Title"] -> Home
// @ViewBag.Message -> Welcome!
// @((int)ViewData["Count"]) -> 42 (cast needed for ViewData)
// @ViewBag.Count -> 42 (no cast for ViewBag)
// Same underlying dictionary — ViewBag.X == ViewData["X"]

Q10. Difference between Response.Redirect() & Server.Transfer()
Response.Redirect(): tells the browser to navigate to a new URL (two HTTP round trips, URL changes). Server.Transfer(): server-side only (one request, URL stays the same in browser, faster, only for same server).

Code:

// Response.Redirect (WebForms / MVC)
// Browser receives 302 -> makes NEW request to /Home/Index
Response.Redirect("/Home/Index");
// Server.Transfer (WebForms only)
// Server executes /OtherPage.aspx — browser URL unchanged
Server.Transfer("OtherPage.aspx");
// In ASP.NET Core MVC equivalent:
return Redirect("/Home/Index"); // 302 redirect
return RedirectToAction("Index", "Home"); // 302 redirect
// No Server.Transfer equivalent in Core — use RedirectToAction
// For permanent redirect:
return RedirectPermanent("/new-url"); // 301

Q11. Difference between Middleware & Filters in .NET Core?
Middleware: works at HTTP pipeline level — runs for EVERY request, before MVC routing. Handles CORS, auth, compression, logging globally. Filters: work inside MVC pipeline — apply to controllers/actions, access action context, ModelState, etc.

Code:

// Middleware — runs for everything
app.Use(async (ctx, next) => {
    Console.WriteLine("Before — any request");
    await next();
    Console.WriteLine("After — any response");
});
// Action Filter — runs only for MVC actions
public class LogActionFilter : IActionFilter {
    public void OnActionExecuting(ActionExecutingContext ctx) =>
        Console.WriteLine($"Before action: {ctx.ActionDescriptor.DisplayName}");
    public void OnActionExecuted(ActionExecutedContext ctx) =>
        Console.WriteLine("After action");
}
// Apply filter on controller
[ServiceFilter(typeof(LogActionFilter))]
public class OrderController : Controller { /* ... */ }
// Key difference:
// Middleware: no access to controllers/models, runs before routing
// Filters: MVC-aware, access ModelState, ActionDescriptor, Result

Q12. How the middleware architecture works end to end
Request enters middleware pipeline -> each middleware decides to call next() or short-circuit -> action executes -> response travels back through each middleware in reverse.

Code:

// Pipeline (order matters)
app.UseExceptionHandler("/Error"); // outermost — catch all
app.UseHttpsRedirection();
app.UseStaticFiles(); // short-circuits for static files
app.UseRouting();
app.UseAuthentication(); // who are you?
app.UseAuthorization(); // what can you do?
app.MapControllers();
// Flow visualised:
// -> ExceptionHandler -> Https -> Static -> Routing -> Auth -> AuthZ -> Controller
// <- ExceptionHandler <- Https <- Static <- Routing <- Auth <- AuthZ <- Response

Q13. Why are we creating middleware? What's the main use?
Middleware handles cross-cutting concerns that apply to ALL or MOST requests: global exception handling, request logging, authentication checks, response compression, CORS, rate limiting, custom headers.

Q14. Have you used/created custom middlewares?
Yes. Example: request-ID injection middleware that stamps every request with a unique ID for tracing.

Code:

public class RequestIdMiddleware {
    private readonly RequestDelegate _next;
    public RequestIdMiddleware(RequestDelegate next) => _next = next;
    public async Task InvokeAsync(HttpContext ctx) {
        var id = Guid.NewGuid().ToString("N")[..8];
        ctx.Response.Headers["X-Request-Id"] = id;
        ctx.Items["RequestId"] = id;
        await _next(ctx);
    }
}
// Register
app.UseMiddleware<RequestIdMiddleware>();

Q15. What is short-circuit in middleware?
Short-circuit means a middleware returns a response WITHOUT calling next() — the remaining pipeline is skipped. Used for auth failures, IP blocks, static files.

Code:

app.Use(async (ctx, next) => {
    if (ctx.Request.Headers["X-Api-Key"] != "secret-key") {
        ctx.Response.StatusCode = 401;
        await ctx.Response.WriteAsync("Unauthorised");
        return; // SHORT CIRCUIT — next() NOT called
    }
    await next(); // continue pipeline
});
// app.Run() always short-circuits (terminal middleware)
app.Run(async ctx => {
    await ctx.Response.WriteAsync("Terminal — no next()");
});

Q16. What is the advantage of .NET Core compared to .NET Framework?
Cross-platform (Windows/Linux/Mac), open-source, high performance (Kestrel), side-by-side versioning, smaller footprint, built-in DI, Docker/cloud-native ready.

Q17. How do we define the scope of an object in .NET Core?
Register in DI container with AddTransient, AddScoped, or AddSingleton in Program.cs.
builder.Services.AddTransient<IEmailService, EmailService>(); // new every injection
builder.Services.AddScoped<IOrderRepo, OrderRepo>(); // new per HTTP request
builder.Services.AddSingleton<ICacheService, CacheService>(); // one for app lifetime

Q18. How many ways can we define dependency injection?
Three ways: Constructor injection (recommended), Property injection, Method injection.
// 1. Constructor injection (PREFERRED)
public class OrderService {
    private readonly IRepo _repo;
    public OrderService(IRepo repo) => _repo = repo; // injected via ctor
}
// 2. Property injection (via [FromServices] or manual)
public class ReportController : Controller {
    [FromServices] public ILogger<ReportController> Logger { get; set; }
}
// 3. Method injection (rare, for action methods)
public IActionResult Get([FromServices] IProductService svc) =>
    Ok(svc.GetAll());

Q19. How are we defining/managing security for your APIs?
JWT bearer tokens for authentication, role/policy-based authorisation, HTTPS enforced, CORS configured, input validation, rate limiting, secrets in Azure Key Vault.

Q20. How are we generating the JWT token and after that how to validate it?

Code:

// Generate
public string GenerateToken(User user) {
    var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_secret));
    var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
    var token = new JwtSecurityToken(
        issuer: "myapp",
        audience: "users",
        claims: new[] {
            new Claim(ClaimTypes.NameIdentifier, user.Id.ToString()),
            new Claim(ClaimTypes.Role, user.Role)
        },
        expires: DateTime.UtcNow.AddHours(1),
        signingCredentials: creds);
    return new JwtSecurityTokenHandler().WriteToken(token);
}
// Validate — done automatically by AddJwtBearer middleware
// Manual validate:
var handler = new JwtSecurityTokenHandler();
handler.ValidateToken(tokenString, validationParams, out SecurityToken validated);
var jwt = (JwtSecurityToken)validated;
var userId = jwt.Claims.First(c => c.Type == ClaimTypes.NameIdentifier).Value;

Q21. Difference between REST & API?
API (Application Programming Interface): any interface that lets two systems communicate (REST, SOAP, GraphQL, RPC). REST: a specific architectural STYLE for APIs over HTTP using stateless request-response with resources identified by URLs.

Q22. What are the protocols used in REST APIs?
HTTP/HTTPS (standard). REST is protocol-agnostic by definition but in practice almost always uses HTTP. Methods: GET, POST, PUT, PATCH, DELETE.

                 SECTION 3: .NET CORE & ASP.NET (120 Questions — Key Answers)

Q1. What is CLR (Common Language Runtime)?
CLR is the runtime engine of .NET. It compiles IL (Intermediate Language) to native machine code via JIT, manages memory (GC), enforces type safety, handles exceptions, and provides security sandboxing.

Q2. Difference between Managed vs Unmanaged code.
Managed: executed by CLR — automatic GC, type-safe (C#, VB.NET). Unmanaged: executed directly by OS — manual memory (C++, Assembly). Interop via P/Invoke.

Q3. What are Generics in C#?
Generics allow type-safe, reusable classes/methods with a type parameter. Avoids boxing/unboxing overhead. E.g. List<T>, Dictionary<K,V>.

Q4. What are Extension Methods in C#?
Static methods with this on first parameter that appear as instance methods on the extended type. Used extensively in LINQ.

Q5. What are Delegates in C#?
Type-safe function pointers. Hold references to methods matching a signature. Built-ins: Action, Func, Predicate.

Q6. Explain the 'using' statement in C#.
Ensures IDisposable objects are disposed even if an exception occurs. Equivalent to try-finally with Dispose().

Q7. Difference between IEnumerable vs IQueryable.
IEnumerable: LINQ to Objects — filters in-memory. IQueryable: translates queries to SQL — filters on server. Use IQueryable for DB queries.

Q8. Explain Garbage Collection in C#.
GC automatically reclaims unreachable managed memory. Three generations: Gen 0 (short-lived), Gen 1, Gen 2 (long-lived). Call GC.Collect() only in exceptional cases.

Q9. Difference between async/await and Task/Thread.
Thread: OS-level, heavy. Task: lightweight work item, pool-backed. async/await: non-blocking syntax over Task — keeps thread free while waiting.
// Thread — heavy, manual management
var thread = new Thread(() => Console.WriteLine("Thread running"));
thread.Start();
// Task — lightweight, pool-backed
var task = Task.Run(() => Console.WriteLine("Task running"));
await task;
// async/await — non-blocking, readable
public async Task<List<Product>> GetProductsAsync() {
    // Thread is FREE while waiting for DB
    var products = await _db.Products.ToListAsync();
    return products;
}
// Parallel — CPU-bound work
int[] numbers = Enumerable.Range(1, 1_000_000).ToArray();
int sum = 0;
Parallel.ForEach(numbers, n => Interlocked.Add(ref sum, n));

Q10. What is Parallel Programming in C#?
Running work on multiple CPU cores simultaneously. Parallel.For, Parallel.ForEach, PLINQ, Task.WhenAll.

Q13. Difference between Dependency Injection lifetimes.
Transient: new every injection. Scoped: new per HTTP request. Singleton: one instance for app lifetime.
builder.Services.AddTransient<IOperationTransient, Operation>();
builder.Services.AddScoped<IOperationScoped, Operation>();
builder.Services.AddSingleton<IOperationSingleton, Operation>();

Q14. Explain Authentication vs Authorization.
Authentication: WHO are you? (identity — JWT, cookies). Authorization: WHAT can you do? (permissions — roles, policies).

Q15. What is JWT (JSON Web Token)?
Three base64url-encoded parts separated by dots: Header (alg+typ), Payload (claims), Signature (HMAC/RSA). Stateless — server verifies without session store.

Q16. Explain REST API principles.
6 constraints: Client-Server, Stateless, Cacheable, Uniform Interface, Layered System, Code on Demand (optional).

Q17. Difference between PUT vs PATCH.
PUT: replace entire resource (idempotent). PATCH: partial update (idempotent in practice). Both are idempotent.

Q18. How to handle Global Exception Handling in .NET Core?
Middleware (ExceptionHandlingMiddleware) or UseExceptionHandler(). Catches all unhandled exceptions, returns consistent error response.

Q19. How to secure APIs from common vulnerabilities?
JWT/OAuth auth, HTTPS, input validation, parameterised queries (SQL injection), CORS policy, rate limiting, secrets in Key Vault, [Authorize] attributes.

Q20. What is Kestrel web server?
Built-in, cross-platform, high-performance HTTP server in ASP.NET Core. Serves requests directly or behind a reverse proxy (IIS/Nginx).

Q22. Explain concept of reverse proxy?
A server that receives client requests and forwards them to backend servers. Client talks to proxy, not the backend directly. Provides SSL, caching, load balancing.

Q75. What is CORS policy?
Cross-Origin Resource Sharing — browser security mechanism. Server explicitly allows cross-domain AJAX calls via Access-Control-Allow-Origin headers.

Q76. Why CORS no issue in Postman but in browser?
Postman does not enforce CORS — it is a browser security policy. The browser checks server headers and blocks if CORS not configured.

Q91. What is API Versioning and its type? How to implement it
Types: URL versioning (/api/v1/), Query string (?ver=1), Header versioning (X-Api-Version), Media type. Use Microsoft.AspNetCore.Mvc.Versioning NuGet.
builder.Services.AddApiVersioning(opt => {
    opt.ReportApiVersions = true;
    opt.AssumeDefaultVersionWhenUnspecified = true;
    opt.DefaultApiVersion = new ApiVersion(1, 0);
    opt.ApiVersionReader = new UrlSegmentApiVersionReader();
});

                    SECTION 4: ENTITY FRAMEWORK & ORM (25 Questions)

Q1. What is ORM?
Object-Relational Mapper: maps database tables to C# classes. Eliminates boilerplate SQL. Examples: EF Core, Dapper, NHibernate.

Q3. What is Dapper?
Micro-ORM: executes raw SQL and maps results to C# objects. Faster than EF Core for read-heavy scenarios. No migrations/change tracking.

Q4. What is EF Core?
Full ORM by Microsoft: LINQ-to-SQL, change tracking, migrations, lazy/eager loading, Code First/Database First.

Q5. EF Core vs EF Framework?
EF Core: cross-platform, .NET Core/5+, faster, more features (filtered includes, TPT, etc.). EF Framework: Windows/.NET Framework only, legacy.

Q6. What are navigation properties in EF Core?
Properties that represent relationships between entities. EF Core uses them for JOINs. E.g. public List<Order> Orders in Customer class.

Q9. Code first vs Database first?
Code First: create models -> generate DB (new projects, clean slate). Database First: existing DB -> scaffold models (legacy databases).

Q10. Commands used for code first
dotnet ef migrations add InitialCreate
dotnet ef database update
dotnet ef migrations remove
dotnet ef dbcontext scaffold

Q11. What are fluent APIs?
Method chaining in OnModelCreating to configure entity mappings without data annotations. More powerful and explicit than attributes.

Q12. How do you call a Stored Procedure from EF core?
_db.Database.ExecuteSqlRawAsync("EXEC sp_Name @p0", value)
// or
_db.Set<T>().FromSqlRaw("EXEC sp_Name {0}", value).ToListAsync()

Q13. What is lazy loading?
Navigation property data loaded ON DEMAND — only when accessed. Requires UseLazyLoadingProxies(). Can cause N+1 query problem.

Q14. Eager loading in EF Core?
Load related data up-front using .Include() and .ThenInclude(). Single DB query with JOIN. Preferred for known relationships.

Q15. Tracking and Non Tracking in EF Core?
Tracking (default): EF watches entity changes -> SaveChanges() persists. No-Tracking (.AsNoTracking()): read-only, faster, less memory.

Q24. AsNoTracking — what does it mean?
Entities returned are NOT tracked by ChangeTracker. No overhead for change detection. Use for read-only queries for better performance.

EF Core Complete Setup Example
// 1. Entity
public class Employee {
    public int Id { get; set; }
    public string Name { get; set; }
    public decimal Salary { get; set; }
    public int DeptId { get; set; }
    public Department Department { get; set; } // nav property
}
// 2. DbContext
public class AppDbContext : DbContext {
    public AppDbContext(DbContextOptions<AppDbContext> opts) : base(opts) { }
    public DbSet<Employee> Employees { get; set; }
    public DbSet<Department> Departments { get; set; }
    protected override void OnModelCreating(ModelBuilder mb) {
        mb.Entity<Employee>()
            .HasOne(e => e.Department)
            .WithMany(d => d.Employees)
            .HasForeignKey(e => e.DeptId);
        mb.Entity<Employee>()
            .Property(e => e.Salary).HasColumnType("decimal(18,2)");
    }
}
// 3. Register
builder.Services.AddDbContext<AppDbContext>(opt =>
    opt.UseSqlServer(builder.Configuration.GetConnectionString("Default")));
// 4. Usage
var emp = await _db.Employees.FindAsync(5);
var emps = await _db.Employees
    .Include(e => e.Department)
    .Where(e => e.Salary > 50000)
    .AsNoTracking()
    .ToListAsync();
// 5. Explicit transaction
using var tx = await _db.Database.BeginTransactionAsync();
try {
    _db.Employees.Add(new Employee { Name = "Vamshi", Salary = 80000 });
    await _db.SaveChangesAsync();
    await tx.CommitAsync();
} catch {
    await tx.RollbackAsync();
}

                                         SECTION 5: SQL SERVER (61 Questions)

Q1. Explain Clustered vs Non-Clustered Indexes.
Clustered: 1 per table, determines physical row order, data pages at leaf — fast range queries. Non-Clustered: multiple per table, separate B-tree with pointer to data — fast point lookups. Primary key is clustered by default.

Q2. What is an Execution Plan in SQL?
Visual/text representation of how SQL Server executes a query. Shows seeks vs scans, join types, cost estimates. View in SSMS with Ctrl+M or SET STATISTICS IO ON.

Q3. Difference between UNION vs UNION ALL.
UNION: removes duplicates (sorts internally — slower). UNION ALL: keeps all rows (no sort — faster). Use UNION ALL unless duplicates must be removed.

Q4. Explain Normalization in SQL.
Organising tables to reduce redundancy and dependency. 1NF: atomic values. 2NF: no partial dependency. 3NF: no transitive dependency. BCNF: stricter 3NF.

Q5. What is CTE (Common Table Expression)?
Temporary named result set within a query using WITH clause. Improves readability. Supports recursion for hierarchical data.

Q6. What are Stored Procedures vs Functions?
SP: can DML, no return required, call with EXEC, transaction support. Function: must return value, used in SELECT, cannot DML (scalar/table-valued).

Q7. What is SQL Injection and how to prevent it?
Attacker injects malicious SQL via input. Prevent: parameterised queries, stored procedures, ORM, input validation, least privilege.

Q8. Explain Triggers in SQL and their types.
Code that auto-executes on INSERT/UPDATE/DELETE. AFTER trigger: post-operation. INSTEAD OF trigger: replaces operation. Used for auditing, business rules.

Q9. What is Deadlock in SQL? How to prevent it?
Two transactions each waiting for the other's lock — circular wait. Prevent: consistent lock order, short transactions, appropriate isolation level, NOLOCK hint.

Q17. ISNULL vs Coalesce
ISNULL(expr, replacement): SQL Server specific, 2 args, returns same type as first arg. COALESCE(a,b,c,...): ANSI standard, multiple args, returns first non-null.

Q18. Truncate vs Delete
TRUNCATE: removes all rows, no WHERE, no triggers, minimal logging, resets identity, faster — cannot rollback in some DBs. DELETE: row-by-row, supports WHERE/triggers, fully logged, can rollback.

Q27. What is ROW_NUMBER?
Window function assigning sequential integers (1,2,3...) to rows within a partition, ordered by specified column. No gaps, no ties — always unique.

Q28. Rank vs DenseRank
RANK(): ties get same rank, next rank SKIPS (1,1,3). DENSE_RANK(): ties get same rank, NO skip (1,1,2).

Q29. What are Magic tables?
Inserted and Deleted virtual tables inside triggers. Inserted: new values (after INSERT/UPDATE). Deleted: old values (after DELETE/UPDATE).

Q32. What is isolation level?
Controls visibility of uncommitted data between concurrent transactions. Levels: Read Uncommitted, Read Committed (default), Repeatable Read, Serializable, Snapshot.

Q34. MERGE Statement
Combines INSERT, UPDATE, DELETE in one statement based on a condition. Source vs Target.

Q36. Difference between SQL vs NoSQL.
SQL: relational, schema, ACID, JOINs — structured data. NoSQL: schema-less, eventual consistency, horizontal scale — unstructured/semi-structured. Types: document (MongoDB), key-value (Redis), column (Cassandra), graph (Neo4j).

SQL Code Examples
Indexes, CTE, Window Functions, Nth Salary
-- INDEXES
CREATE CLUSTERED INDEX IX_EmpPK ON Employees(Id);
CREATE NONCLUSTERED INDEX IX_EmpName ON Employees(LastName, FirstName) INCLUDE (Salary);

-- CTE — simple
WITH HighEarners AS (
    SELECT Id, Name, Salary,
        DENSE_RANK() OVER (ORDER BY Salary DESC) AS Rnk
    FROM Employees
)
SELECT * FROM HighEarners WHERE Rnk <= 3;

-- CTE — recursive (org hierarchy)
WITH OrgTree AS (
    SELECT Id, Name, ManagerId, 1 AS Level
    FROM Employees WHERE ManagerId IS NULL
    UNION ALL
    SELECT e.Id, e.Name, e.ManagerId, ot.Level + 1
    FROM Employees e JOIN OrgTree ot ON e.ManagerId = ot.Id
)
SELECT * FROM OrgTree ORDER BY Level;

-- Nth highest salary (N=3)
SELECT TOP 1 Salary
FROM (SELECT DISTINCT Salary, DENSE_RANK() OVER (ORDER BY Salary DESC) R
    FROM Employees) t
WHERE R = 3;

-- ROW_NUMBER / RANK / DENSE_RANK
SELECT Name, Salary,
    ROW_NUMBER() OVER (ORDER BY Salary DESC) AS RowNum,
    RANK() OVER (ORDER BY Salary DESC) AS Rnk,
    DENSE_RANK() OVER (ORDER BY Salary DESC) AS DenseRnk
FROM Employees;

Stored Procedure, Trigger, Transaction
-- Stored Procedure
CREATE PROCEDURE sp_GetEmployeesByDept
    @DeptId INT, @MinSalary DECIMAL = 0
AS BEGIN
    SELECT Id, Name, Salary
    FROM Employees
    WHERE DeptId = @DeptId AND Salary >= @MinSalary
    ORDER BY Salary DESC;
END
EXEC sp_GetEmployeesByDept @DeptId = 5, @MinSalary = 50000;

-- Trigger (audit)
CREATE TRIGGER trg_EmpSalaryAudit
ON Employees AFTER UPDATE
AS BEGIN
    INSERT INTO AuditLog (EmployeeId, OldSalary, NewSalary, ChangedAt)
    SELECT d.Id, d.Salary, i.Salary, GETUTCDATE()
    FROM DELETED d JOIN INSERTED i ON d.Id = i.Id
    WHERE d.Salary != i.Salary;
END

-- Transaction
BEGIN TRY
    BEGIN TRANSACTION
        UPDATE Accounts SET Balance -= 500 WHERE Id = 1; -- debit
        UPDATE Accounts SET Balance += 500 WHERE Id = 2; -- credit
    COMMIT TRANSACTION
END TRY
BEGIN CATCH
    ROLLBACK TRANSACTION
    THROW;
END CATCH

-- MERGE
MERGE Employees AS Target
USING NewEmployees AS Source ON Target.Email = Source.Email
WHEN MATCHED THEN UPDATE SET Target.Name = Source.Name
WHEN NOT MATCHED THEN INSERT (Name, Email) VALUES (Source.Name, Source.Email)
WHEN NOT MATCHED BY SOURCE THEN DELETE;

-- Delete duplicates
DELETE FROM Employees
WHERE Id NOT IN (
    SELECT MIN(Id) FROM Employees GROUP BY Email
);

INTERVIEW ANSWERS — PART 3
Design Patterns  ·  SOLID  ·  Angular  ·  Azure  ·  DevOps  ·  Coding Problems
SECTION 6: DESIGN PATTERNS & ARCHITECTURE (57 Questions)
Q2. What is Design Pattern and why do we need?
A design pattern is a named, reusable solution to a commonly occurring software design problem. Patterns are NOT copy-paste code — they are templates / blueprints. They save time because smarter developers already solved the problem. They give teams a shared vocabulary.

Q3. Types of Design Pattern — Creational, Structural, Behavioural
CREATIONAL — how objects are created: Singleton, Factory Method, Abstract Factory, Builder, Prototype
STRUCTURAL — how classes/objects are composed: Adapter, Decorator, Facade, Proxy, Composite, Bridge, Flyweight
BEHAVIOURAL — how objects communicate: Strategy, Observer, Command, Iterator, State, Chain of Responsibility, Template Method, Mediator, CQRS

Q1/Q6. Singleton Pattern — Thread-Safe Implementation
Singleton ensures only ONE instance of a class exists for the entire application. Common uses: Logger, Configuration, DB connection factory. Key rule: private constructor so nobody can call new outside the class.

Code:

// IMPLEMENTATION 1: Double-Check Locking
public sealed class AppLogger
{
    private static AppLogger _instance;
    private static readonly object _lock = new object();
    private AppLogger() { }
    public static AppLogger Instance
    {
        get
        {
            if (_instance == null) // first check (no lock — fast path)
            {
                lock (_lock) // only one thread enters at a time
                {
                    if (_instance == null) // second check inside lock — safe
                        _instance = new AppLogger();
                }
            }
            return _instance;
        }
    }
    public void Log(string msg) =>
        Console.WriteLine($"[{DateTime.Now:HH:mm:ss}] {msg}");
}

// IMPLEMENTATION 2: Lazy<T> (RECOMMENDED — simpler, built-in thread safety)
public sealed class Config
{
    private static readonly Lazy<Config> _lazy =
        new Lazy<Config>(() => new Config());
    public static Config Instance => _lazy.Value;
    private Config() { }
    public string Theme { get; set; } = "Dark";
}

// USAGE
AppLogger.Instance.Log("App started");
AppLogger.Instance.Log("Order placed");
Console.WriteLine(Config.Instance.Theme); // Dark

Q7. Connection pooling in Singleton — why problematic from DB perspective?
Many developers think 'put DbContext in Singleton so we reuse one connection.' This is WRONG because DbContext is NOT thread-safe. Two simultaneous requests will corrupt each other's tracked entity state. Correct approach: register DbContext as SCOPED (one per HTTP request). ADO.NET connection pooling happens transparently at the driver level.
// WRONG — DbContext as Singleton
builder.Services.AddSingleton<AppDbContext>(); // DO NOT DO THIS

// CORRECT — new DbContext per HTTP request
builder.Services.AddDbContext<AppDbContext>(opt =>
    opt.UseSqlServer(connectionString));
// AddDbContext registers as Scoped automatically

Q8. Singleton pattern disadvantage
1. Hard to unit test — global state is shared between tests; must reset between tests.
2. Hidden dependency — class secretly depends on a global, not declared in constructor.
3. Violates Single Responsibility — manages its own lifecycle AND its own logic.
4. Thread safety complexity — need locking code.
5. Cannot easily subclass or swap implementation.
6. Lifetime mismatch — injecting Scoped service into Singleton causes CaptiveDependency bug.

Q10. What is Strategy DP?
Strategy defines a FAMILY of algorithms, puts each in its own class, and makes them interchangeable at runtime. Problem it solves: avoid big if-else / switch blocks when behaviour needs to vary. Real world: payment methods, sorting algorithms, discount rules, export formats.
Code:
// Step 1: Define the strategy interface (the CONTRACT)
public interface IDiscountStrategy
{
    decimal Apply(decimal originalPrice);
}
// Step 2: Concrete strategies
public class NoDiscount : IDiscountStrategy
{
    public decimal Apply(decimal price) => price;
}
public class FestivalDiscount : IDiscountStrategy
{
    public decimal Apply(decimal price) => price * 0.80m; // 20% off
}
public class ClearanceDiscount : IDiscountStrategy
{
    public decimal Apply(decimal price) => price * 0.50m; // 50% off
}
// Step 3: Context — holds strategy, delegates to it
public class ShoppingCart
{
    private IDiscountStrategy _discount = new NoDiscount();
    public void SetDiscount(IDiscountStrategy strategy) => _discount = strategy;
    public decimal Checkout(decimal total)
    {
        decimal finalPrice = _discount.Apply(total);
        Console.WriteLine($"Original: {total}, Final: {finalPrice}");
        return finalPrice;
    }
}
// Step 4: Usage — swap strategy without changing Cart
var cart = new ShoppingCart();
cart.Checkout(1000); // 1000 (NoDiscount)
cart.SetDiscount(new FestivalDiscount());
cart.Checkout(1000); // 800 (20% off)
cart.SetDiscount(new ClearanceDiscount());
cart.Checkout(1000); // 500 (50% off)

Q11. What is Adapter DP?
Adapter makes an incompatible interface work with client code. Analogy: a power plug adapter lets a 3-pin plug work in a 2-pin socket. Real world: wrapping a legacy class, third-party library, or external API so it matches your internal interface.
Code:
// Our application expects this interface (the TARGET)
public interface IMessageSender
{
    void Send(string to, string message);
}
// Third-party legacy SMS library we cannot modify (the ADAPTEE)
public class LegacySmsLib
{
    public void SendSms(string phoneNumber, string text, bool isUrgent, string senderId)
    {
        Console.WriteLine($"SMS to {phoneNumber}: {text}");
    }
}
// ADAPTER — wraps the incompatible class, exposes our interface
public class SmsAdapter : IMessageSender
{
    private readonly LegacySmsLib _legacy;
    public SmsAdapter() { _legacy = new LegacySmsLib(); }
    public void Send(string to, string message)
    {
        _legacy.SendSms(to, message, isUrgent: false, senderId: "MYAPP");
    }
}
// Client code
public class NotificationService
{
    private readonly IMessageSender _sender;
    public NotificationService(IMessageSender sender) => _sender = sender;
    public void NotifyUser(string phone, string msg) => _sender.Send(phone, msg);
}
IMessageSender sender = new SmsAdapter();
var service = new NotificationService(sender);
service.NotifyUser("+1234567890", "Your order has shipped!");

Q13. What is Repository DP? List its advantages
Repository hides all data-access logic behind an interface. Business logic talks to the interface — it does not know (or care) if data comes from SQL, Cosmos DB, or a file. Advantages: 1. Testable — mock IRepository in unit tests without a real database. 2. Swappable — change from SQL to Mongo by swapping implementation. 3. Single place — query logic lives in one class. 4. Consistent API — Add, GetById, GetAll, Update, Delete everywhere.

Code:

// Step 1: Define interface
public interface IProductRepository
{
    Task<Product?> GetByIdAsync(int id);
    Task<IEnumerable<Product>> GetAllAsync();
    Task AddAsync(Product product);
    Task UpdateAsync(Product product);
    Task DeleteAsync(int id);
}
// Step 2: EF Core implementation
public class EfProductRepository : IProductRepository
{
    private readonly AppDbContext _db;
    public EfProductRepository(AppDbContext db) => _db = db;
    public async Task<Product?> GetByIdAsync(int id) => await _db.Products.FindAsync(id);
    public async Task<IEnumerable<Product>> GetAllAsync() =>
        await _db.Products.AsNoTracking().ToListAsync();
    public async Task AddAsync(Product p) { _db.Products.Add(p); await _db.SaveChangesAsync(); }
    public async Task UpdateAsync(Product p) { _db.Products.Update(p); await _db.SaveChangesAsync(); }
    public async Task DeleteAsync(int id)
    {
        var p = await GetByIdAsync(id);
        if (p != null) { _db.Products.Remove(p); await _db.SaveChangesAsync(); }
    }
}
// Step 3: Register
builder.Services.AddScoped<IProductRepository, EfProductRepository>();

Q14. What is CQRS DP?
CQRS = Command Query Responsibility Segregation. Separate reads (Queries) from writes (Commands) into completely different models. Query: returns data, never changes state. Command: changes state, returns minimal data. Why: read and write loads are different — reads can be 100x more frequent; each side can be optimised independently.
Code:
// COMMAND: changes state
public record CreateOrderCommand(int CustomerId, List<int> ProductIds)
    : IRequest<int>;

public class CreateOrderHandler : IRequestHandler<CreateOrderCommand, int>
{
    private readonly IOrderRepository _repo;
    public CreateOrderHandler(IOrderRepository repo) => _repo = repo;
    public async Task<int> Handle(CreateOrderCommand cmd, CancellationToken ct)
    {
        var order = new Order {
            CustomerId = cmd.CustomerId,
            Items = cmd.ProductIds.Select(id => new OrderItem { ProductId = id }).ToList(),
            CreatedAt = DateTime.UtcNow
        };
        await _repo.AddAsync(order);
        return order.Id;
    }
}

// QUERY: returns data, zero side effects
public record GetOrderQuery(int OrderId) : IRequest<OrderDto?>;

public class GetOrderHandler : IRequestHandler<GetOrderQuery, OrderDto?>
{
    private readonly IOrderReadDb _readDb;
    public GetOrderHandler(IOrderReadDb readDb) => _readDb = readDb;
    public async Task<OrderDto?> Handle(GetOrderQuery q, CancellationToken ct) =>
        await _readDb.GetOrderDtoAsync(q.OrderId);
}

// Controller: thin, dispatches via MediatR
[ApiController, Route("api/orders")]
public class OrdersController : ControllerBase
{
    private readonly IMediator _mediator;
    public OrdersController(IMediator mediator) => _mediator = mediator;
    [HttpPost]
    public async Task<IActionResult> Create([FromBody] CreateOrderCommand cmd)
    {
        int newId = await _mediator.Send(cmd);
        return CreatedAtAction(nameof(Get), new { id = newId }, new { id = newId });
    }
    [HttpGet("{id}")]
    public async Task<IActionResult> Get(int id)
    {
        var dto = await _mediator.Send(new GetOrderQuery(id));
        return dto is null ? NotFound() : Ok(dto);
    }
}

Q15. What are 3 important elements of CQRS?
1. COMMAND — intent to mutate state (CreateOrder, CancelFlight). Carries the input data.
2. QUERY — request for data (GetOrder, ListFlights). Must not change anything.
3. HANDLER — processes the command or query. One handler per command/query. Contains the actual logic.

Q20. Have you worked on Clean Architecture?
Clean Architecture = 4 concentric circles:
1. Domain (innermost): Entities, Value Objects, Domain Events, interfaces — ZERO external dependencies.
2. Application: Use Cases, CQRS Handlers, DTOs — depends only on Domain.
3. Infrastructure: EF Core, SQL, Azure, Email — depends on Application interfaces.
4. Presentation: API Controllers, minimal API — depends on Application.
Dependency rule: arrows point INWARD only. Domain knows nothing about EF Core or HTTP.

Q21. What are Microservices and their advantages and disadvantages?
Microservices: independently deployable services each owning one business capability and its own DB.
Advantages: Each service scales independently. Independent deployment. Technology diversity. Fault isolation.
Disadvantages: Distributed system complexity. Eventual consistency instead of ACID. Harder debugging. Operational overhead.

Q22. Monolithic vs Microservices
Monolith: all code in one codebase, one deployment, one DB. Simple ops. Scale EVERYTHING together. Fast initially.
Microservices: many codebases, many deployments, each service owns its DB. Complex ops. Scale what needs scaling. Better for large teams.
Rule of thumb: start monolith, extract to microservices when team/load demands it.

Q23. Why do we use an API Gateway?
Without gateway: clients talk to 10 services at 10 different URLs — auth in every service. With gateway: one URL, one auth check, one SSL cert, one rate limiter. Provides: routing, auth, rate limiting, SSL, request aggregation, caching, logging. Examples: Azure API Management (APIM), Kong, Ocelot (.NET library), AWS API Gateway.

Q25. Difference between rate limiting and load balancing
Rate Limiting: control how many requests a SINGLE CLIENT can send per time window. Prevents abuse.
Load Balancing: distribute requests across MULTIPLE SERVER INSTANCES for availability and performance.

Q26. Where should rate limiting be applied?
API Gateway level (first defence — before traffic reaches services). Or ASP.NET Core 7+ built-in middleware.
Code:
builder.Services.AddRateLimiter(opt =>
{
    opt.AddFixedWindowLimiter("fixed", cfg =>
    {
        cfg.PermitLimit = 100;
        cfg.Window = TimeSpan.FromMinutes(1);
        cfg.QueueProcessingOrder = QueueProcessingOrder.OldestFirst;
        cfg.QueueLimit = 10;
    });
    opt.RejectionStatusCode = StatusCodes.Status429TooManyRequests;
});
app.UseRateLimiter();
app.MapGet("/api/search", SearchHandler).RequireRateLimiting("fixed");

Q28. How do microservices communicate?
SYNCHRONOUS (request-response, tight coupling): HTTP/REST — simple, widely supported. gRPC — binary protocol, typed contracts (Protobuf), faster than JSON.
ASYNCHRONOUS (event-driven, loose coupling): Azure Service Bus — guaranteed delivery, dead-letter, retry. RabbitMQ — open-source, flexible routing, pub-sub. Kafka — high-throughput event streaming, consumer groups, replay.

Q33. Strategic DDD vs Tactical DDD.
Strategic DDD: high-level — WHERE to draw boundaries. Bounded Contexts, Context Maps, Subdomains, Ubiquitous Language. Done with domain experts BEFORE writing code.
Tactical DDD: implementation-level — HOW to write code inside a bounded context. Entities, Value Objects, Aggregates, Repositories, Domain Services, Domain Events.

Q37. What is a SAGA pattern?
Manages distributed transactions without 2-phase commit. Each step has a FORWARD action and a COMPENSATING action (undo). CHOREOGRAPHY: services react to events from each other — decentralised. ORCHESTRATION: one saga orchestrator class calls each service in sequence — centralised, easier to reason about.

Q39. Entity vs Value Object vs Service
ENTITY: has unique identity (OrderId=42), mutable, tracked over time.
VALUE OBJECT: defined by attributes, no identity, immutable — Money(100, USD), Address.
DOMAIN SERVICE: logic that does not naturally belong to an entity — TaxCalculator, CurrencyConverter.

Q40. Aggregate root
An aggregate is a cluster of entities/VOs treated as one unit. The ROOT is the only entry point — external code references the root only, never inner entities. Enforces invariants: Order.AddItem() validates max items, not caller.

Q52. How to avoid duplicate payments in a booking system?
IDEMPOTENCY KEY: client generates UUID per attempt. API stores key in DB. Second call with same key returns first result without re-charging. Redis with TTL for quick lookup.

                             SECTION 7: SOLID PRINCIPLES (18 Questions)

Q1. What is SOLID principle and why implement?
Five design principles that make object-oriented code maintainable, extensible, and testable.
S — Single Responsibility Principle
O — Open/Closed Principle
L — Liskov Substitution Principle
I — Interface Segregation Principle
D — Dependency Inversion Principle
Why: code that violates SOLID becomes hard to change, hard to test, and hard to extend.

Q2. State all the principles with example

Code:
// S: Single Responsibility — one reason to change
// WRONG: one class doing everything
public class UserManager
{
    public void CreateUser(string name) { /* DB insert */ }
    public void SendWelcomeEmail(string email) { /* SMTP */ }
    public void LogActivity(string msg) { /* File IO */ }
}
// CORRECT: each class has one job
public class UserService { public void CreateUser(string name) { } }
public class EmailService { public void SendWelcomeEmail(string email) { } }
public class ActivityLog { public void Log(string msg) { } }

// O: Open/Closed — extend without modifying
// CORRECT: each shape knows its own area; AreaCalc never changes
public interface IShape { double Area(); }
public class Circle : IShape { public double R; public double Area() => Math.PI * R * R; }
public class Rectangle : IShape { public double W, H; public double Area() => W * H; }
public class AreaCalc { public double Calc(IShape s) => s.Area(); } // never changes

// L: Liskov Substitution — child must honour parent contract
// CORRECT: restructure with capability interfaces
public interface IFlyable { void Fly(); }
public interface ISwimmable { void Swim(); }
public class Eagle : IFlyable { public void Fly() => Console.WriteLine("Soaring"); }
public class Penguin : ISwimmable { public void Swim() => Console.WriteLine("Swimming"); }

// I: Interface Segregation — small focused interfaces
// CORRECT: split into focused interfaces
public interface IWorkable { void Work(); }
public interface IFeedable { void Eat(); }
public interface ISleepable { void Sleep(); }
public class HumanWorker : IWorkable, IFeedable, ISleepable { ... }
public class RobotWorker : IWorkable { public void Work() { } }

// D: Dependency Inversion — depend on abstractions
// CORRECT: depend on interface, inject concrete via DI
public interface IOrderRepository { Task SaveAsync(Order o); }
public class OrderService
{
    private readonly IOrderRepository _repo;
    public OrderService(IOrderRepository repo) => _repo = repo; // injected
    public async Task Place(Order o) => await _repo.SaveAsync(o);
}

Q3. What is Liskov Substitution Principle — explain with example
If S is a subtype of T, objects of type T can be replaced with S without breaking the program. Simply: code that works with the BASE class must also work correctly with any CHILD class. Violation symptom: child class throws NotImplementedException or does nothing for an inherited method.

Code:

// CORRECT: model what things ARE, not inheritance hierarchy
public interface IShape2 { int Area(); }
public class Rect : IShape2 { public int W, H; public int Area() => W * H; }
public class Square : IShape2 { public int S; public int Area() => S * S; }
// Both implement IShape2 — no surprising behaviour

Q4. Difference between Open/Closed and Liskov principle
OCP: about EXTENSIBILITY — add new behaviour without modifying existing code. Done by using interfaces/abstract classes so new types can be plugged in.
LSP: about CORRECTNESS of substitution — when you DO subclass, the child must honour the parent's promises. No surprise exceptions, no weaker behaviour.

Q5. Difference between Liskov vs ISP?
LSP: about CLASS inheritance correctness — child must be substitutable for parent.
ISP: about INTERFACE design — clients should not be forced to implement methods they do not use.
LSP is violated when: child throws NotImplemented or weakens a method.
ISP is violated when: one fat interface forces classes to implement irrelevant methods.

Q6. How do you design API for different payment gateways?
Strategy + Factory + DI for payment gateways.

Code:

// Step 1: Define the payment contract (ISP — focused interface)
public interface IPaymentGateway
{
    Task<PaymentResult> ChargeAsync(PaymentRequest request);
    Task<RefundResult> RefundAsync(string transactionId, decimal amount);
}
// Step 2: Implement per gateway (OCP)
public class StripeGateway : IPaymentGateway
{
    public async Task<PaymentResult> ChargeAsync(PaymentRequest req)
    {
        Console.WriteLine($"Stripe: charging {req.Amount} {req.Currency}");
        return new PaymentResult { Success = true, TransactionId = Guid.NewGuid().ToString() };
    }
    public async Task<RefundResult> RefundAsync(string txId, decimal amount)
    {
        Console.WriteLine($"Stripe: refunding {amount} for tx {txId}");
        return new RefundResult { Success = true };
    }
}
// Step 3: Factory creates the right gateway (Strategy pattern)
public class PaymentGatewayFactory
{
    private readonly IServiceProvider _sp;
    public PaymentGatewayFactory(IServiceProvider sp) => _sp = sp;
    public IPaymentGateway Create(string provider) => provider.ToLower() switch
    {
        "stripe" => _sp.GetRequiredService<StripeGateway>(),
        "razorpay" => _sp.GetRequiredService<RazorpayGateway>(),
        _ => throw new NotSupportedException($"Unknown provider: {provider}")
    };
}
// Step 4: Service uses interface — unaware of concrete gateway (DIP)
public class CheckoutService
{
    private readonly PaymentGatewayFactory _factory;
    public CheckoutService(PaymentGatewayFactory factory) => _factory = factory;
    public async Task<PaymentResult> ProcessPayment(string provider, PaymentRequest req)
    {
        IPaymentGateway gateway = _factory.Create(provider);
        return await gateway.ChargeAsync(req);
    }
}

Q7. Calculate salary based on grades — Strategy pattern

Code:

public class Employee
{
    public string Name { get; set; }
    public decimal Basic { get; set; }
    public string Grade { get; set; } // A, B, C
}
public interface ISalaryStrategy { decimal Calculate(Employee e); }

public class GradeAStrategy : ISalaryStrategy
{
    // Grade A: basic + 100% basic (HRA) + 50% basic (allowances)
    public decimal Calculate(Employee e) => e.Basic + e.Basic + (e.Basic * 0.5m);
}
public class GradeBStrategy : ISalaryStrategy
{
    public decimal Calculate(Employee e) => e.Basic + (e.Basic * 0.5m) + (e.Basic * 0.2m);
}
public class GradeCStrategy : ISalaryStrategy
{
    public decimal Calculate(Employee e) => e.Basic + (e.Basic * 0.1m);
}

public class Payroll
{
    private readonly Dictionary<string, ISalaryStrategy> _strategies = new()
    {
        ["A"] = new GradeAStrategy(),
        ["B"] = new GradeBStrategy(),
        ["C"] = new GradeCStrategy()
    };
    public decimal GetGrossSalary(Employee emp)
    {
        if (!_strategies.TryGetValue(emp.Grade, out var strategy))
            throw new ArgumentException($"Unknown grade: {emp.Grade}");
        return strategy.Calculate(emp);
    }
}
// Usage
var payroll = new Payroll();
var emp = new Employee { Name = "Vamshi", Basic = 50000, Grade = "A" };
Console.WriteLine($"{emp.Name}: Rs.{payroll.GetGrossSalary(emp):N0}"); // Rs.1,25,000

Q8. Explain D from SOLID with written example
Dependency Inversion — before and after:

Code:

// BEFORE (VIOLATION): high-level depends on low-level concrete
public class ReportGenerator_Bad
{
    private SqlReportRepository _repo = new SqlReportRepository();
    private SmtpEmailSender _email = new SmtpEmailSender();
    public void GenerateAndSend(int reportId, string recipient)
    {
        var data = _repo.GetReportData(reportId);
        var pdf = CreatePdf(data);
        _email.Send(recipient, "Report", pdf);
    }
}
// To unit test — must have real SQL and real SMTP. Impossible to isolate.

// AFTER (CORRECT): depend on abstractions
public interface IReportRepository { ReportData Get(int id); }
public interface IEmailSender { void Send(string to, string subject, byte[] attachment); }
public class ReportGenerator_Good
{
    private readonly IReportRepository _repo;
    private readonly IEmailSender _email;
    public ReportGenerator_Good(IReportRepository repo, IEmailSender email)
    {
        _repo = repo;
        _email = email;
    }
    public void GenerateAndSend(int reportId, string recipient)
    {
        var data = _repo.Get(reportId);
        var pdf = CreatePdf(data);
        _email.Send(recipient, "Report", pdf);
    }
}
// Production: real implementations
builder.Services.AddScoped<IReportRepository, SqlReportRepository>();
builder.Services.AddScoped<IEmailSender, SmtpEmailSender>();
// Tests: fake implementations — no SQL or SMTP needed
var mockRepo = new Mock<IReportRepository>();
var mockEmail = new Mock<IEmailSender>();
var generator = new ReportGenerator_Good(mockRepo.Object, mockEmail.Object);

                           SECTION 8: ANGULAR (135 Questions — Key Answers)
Q1. Why Angular?
Component-based SPA framework. TypeScript-first (type safety). Built-in DI, routing, HTTP client, reactive forms. Two-way binding reduces boilerplate. Strong CLI. Used by enterprise teams at scale.

Q2. Which is the latest version?
Angular 18 (May 2024). Key features: Signals (reactive primitives replacing RxJS for simple state), new control flow (@if, @for, @switch replacing *ngIf/*ngFor), standalone components default, deferred loading (@defer).

Q5. What is AOT?
Ahead-of-Time compilation: Angular compiles HTML templates at BUILD time into efficient JavaScript. Smaller bundle, faster startup, template errors caught at build (not runtime). Enabled by default in ng build --prod.

Q6. What are decorators?
TypeScript metadata annotations. @Component tells Angular this class is a component. @Injectable marks it for DI. @Input/@Output define data flow. Angular reads decorators at runtime to wire everything up.

Q8. How does Angular app start?
main.ts -> bootstrapApplication(AppComponent, appConfig) -> Angular reads AppComponent @Component -> creates component tree -> Router loads first matched route -> renders in <router-outlet>.

Q12. What are modules?
@NgModule: groups related components, directives, pipes. Declares what it has. Imports what it needs. Exports what others can use. In Angular 14+ standalone components can replace modules.

Q13. What is ngModel?
Two-way binding directive: [(ngModel)]='property'. Input change updates property; property change updates input. Requires FormsModule import. Under the hood: [ngModel] + (ngModelChange).

Q15. Lazy loading in routing?
loadComponent: () => import("./orders/orders.component").then(m => m.OrdersComponent)
// Module lazy:
loadChildren: () => import("./admin/admin.module").then(m => m.AdminModule)
Angular compiles each lazy chunk into a separate JS file — not downloaded until user navigates there.

Q16. What are directives and their types?
STRUCTURAL (change DOM): *ngIf, *ngFor, *ngSwitch — prefix * is syntactic sugar for <ng-template>.
ATTRIBUTE (change appearance/behaviour): ngClass, ngStyle, custom directives.
COMPONENT: a directive with a template (most used type).

Q18. Types of data binding?
ONE-WAY component->view: Interpolation {{ name }}, Property binding [src]='imageUrl'.
ONE-WAY view->component: Event binding (click)='handleClick()'.
TWO-WAY: [(ngModel)]='username' — shorthand for [ngModel]='x' (ngModelChange)='x=$event'.

Q21. What is HTTP Interceptor? How to implement it?
Global middleware for HttpClient calls. Intercepts every request/response before they reach handlers. Use for: add JWT header, log all calls, show spinner, refresh expired tokens, transform errors.
@Injectable()
export class AuthInterceptor implements HttpInterceptor {
    constructor(private auth: AuthService, private spinner: SpinnerService) {}
    intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
        const token = this.auth.getToken();
        const authReq = token
            ? req.clone({ setHeaders: { Authorization: `Bearer ${token}` } })
            : req;
        this.spinner.show();
        return next.handle(authReq).pipe(
            catchError((error: HttpErrorResponse) => {
                if (error.status === 401) { this.auth.logout(); }
                if (error.status === 403) { console.error('Access denied'); }
                return throwError(() => error);
            }),
            finalize(() => this.spinner.hide())
        );
    }
}
// Register:
// { provide: HTTP_INTERCEPTORS, useClass: AuthInterceptor, multi: true }

Q24. Ways to pass data between components?
Parent->Child: @Input(). Child->Parent: @Output() EventEmitter. Siblings: shared service with Subject/BehaviorSubject. Deep tree: NgRx store or React-style context. URL: Router params/query params.

Q25. All Life cycle hooks in sequence?
ngOnChanges (before init if @Input) -> ngOnInit (once, after first change detection) -> ngDoCheck (every CD cycle) -> ngAfterContentInit (once after ng-content projected) -> ngAfterContentChecked (every CD) -> ngAfterViewInit (once after view+children init) -> ngAfterViewChecked (every CD) -> ngOnDestroy (before removal).

Q26. Constructor vs ngOnInit
Constructor: TypeScript class initialisation — should ONLY inject dependencies, nothing else. Angular DI calls it.
ngOnInit: Angular lifecycle hook — safe to access @Input values, call HTTP services, setup subscriptions. Called after constructor and first change detection.

Q34. Promise vs Observables
Promise: single value, starts immediately (eager), cannot cancel, .then/.catch.
Observable: multiple values over time, starts only when subscribed (lazy), cancellable with unsubscribe(), rich operators (map, filter, retry, debounce), works with async pipe.

Q35. Observables vs Subject
Observable: COLD — each subscriber gets its own execution (separate HTTP call per subscriber).
Subject: HOT — all subscribers share one stream. Subject is both Observable AND Observer — you can call .next() on it externally.

Q36. Different Types of Subject
Subject: no initial value, late subscribers miss past emissions.
BehaviorSubject(initialValue): holds LAST value, new subscriber gets it immediately. Most used.
ReplaySubject(n): replays last N values to new subscribers.
AsyncSubject: emits ONLY the last value, ONLY on complete.

Q39. Template driven vs Reactive forms?
Template driven: ngModel in template, simple, less code, FormsModule, hard to unit test.
Reactive: FormGroup/FormControl in component TypeScript, explicit, unit testable, dynamic validation, ReactiveFormsModule. PREFER for any form with validation logic.

Q40. What is auth guard in Angular?
Implements CanActivate interface. Returns true (allow navigation) or false/UrlTree (redirect to login). Protects routes from unauthenticated users. Runs BEFORE the component is created.

Q44. RxJS operators?
Creation: of(), from(), interval(), fromEvent().
Transform: map(), switchMap(), mergeMap(), concatMap().
Filter: filter(), debounceTime(), distinctUntilChanged(), take().
Combine: forkJoin(), combineLatest(), merge().
Utility: tap(), catchError(), retry(), finalize(), takeUntil().

Q48. State management in Angular?
Local component state: property / BehaviorSubject in service.
Global state: NgRx (Redux pattern — Actions, Reducers, Store, Selectors, Effects).
Simple shared state: shared service with BehaviorSubject.
Signals (Angular 17+): built-in reactive primitive — simplest option for new code.

Q49. Angular new features (v17-18)?
@if, @for, @switch control flow (no more *ngIf/*ngFor directives). Signals for reactive state. Standalone components default. @defer blocks for deferred loading. New project structure. Built-in SSR setup.

Q44b. switchMap vs mergeMap — real scenario

Code:

// switchMap: CANCEL previous, use only latest
// Use case: search box — user types fast, only care about last search result
this.searchControl.valueChanges.pipe(
    debounceTime(300),
    distinctUntilChanged(),
    switchMap(term =>
        this.productSvc.search(term).pipe(
            catchError(() => of([]))
        )
    )
).subscribe(results => this.results = results);

// mergeMap: run ALL concurrently, merge results
// Use case: download multiple reports simultaneously
const reportIds = [1, 2, 3, 4, 5];
from(reportIds).pipe(
    mergeMap(id => this.reportSvc.download(id))
).subscribe(report => this.addReport(report));

// concatMap: run SEQUENTIALLY, one by one
from(orders).pipe(
    concatMap(order => this.orderSvc.process(order))
).subscribe();

Q116. What is BehaviorSubject
RxJS Subject with initial value. Late subscribers always get latest emission. Expose as Observable for read-only access. Perfect for 'current state' pattern.

Q124. Change detection strategy
Default: check ALL components on every browser event. OnPush: check component only when @Input reference changes OR async pipe emits OR markForCheck() called. OnPush = big performance win for large apps.

Q129. Center div inside div
.parent { display: flex; justify-content: center; align-items: center; height: 100%; }
/* OR */
.parent { display: grid; place-items: center; }
/* OR */
.child { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); }

Q130. Remove duplicates from array
// JavaScript
const unique = [...new Set(array)];
// or
const unique2 = array.filter((v, i, a) => a.indexOf(v) === i);

Q135. CSS grid vs flexbox
Flexbox: ONE dimension (row OR column). Best for component-level alignment. Grid: TWO dimensions (rows AND columns simultaneously). Best for page layout. Use both together: grid for layout, flex for alignment within cells.


This was part of Interview Preparation With Bipin — Let’s Crack It!

Comments

Popular posts from this blog

Angular Architecture

Why should I learn Angular?

Solid Principle