Skip to content

Practical .NET Full Stack Interview Questions

44 questions with answers. Hands-on questions where you write code, a query, a formula or concrete steps.

How to approach these questions

Talk while you work: say your approach first, write the simplest correct version, then improve it and mention edge cases.

Solved — practicalStart practicing
3 QUESTIONS FREESign up to unlock the full question bank and track your progress.Unlock every question and answer, then continue practising company-wise and package-wise.
3 questions free Unlock the rest in seconds
01

Show how to implement IDisposable and use the using statement.

Save to ▾
Show answer
public class FileLogger : IDisposable { private readonly StreamWriter _writer = new("log.txt"); public void Log(string msg) => _writer.WriteLine(msg); public void Dispose() => _writer.Dispose(); } // using declaration disposes at end of scope using var logger = new FileLogger(); logger.Log("Started"); Dispose releases unmanaged resources such as file handles and connections deterministically instead of waiting for the GC.
02

Write a switch expression using pattern matching to calculate shipping cost.

Save to ▾
Show answer
decimal Shipping(Order o) => o switch { { Total: >= 1000 } => 0m, { Country: "IN", Weight: < 2 } => 49m, { Country: "IN" } => 99m, { Weight: > 20 } => throw new ArgumentException("Too heavy"), _ => 499m }; Property and relational patterns replace long if-else chains, and the compiler warns if cases are not exhaustive.
03

Write an extension method that checks whether a string is a valid Indian mobile number.

Save to ▾
Show answer
public static class StringExtensions { public static bool IsIndianMobile(this string? value) => value is not null && System.Text.RegularExpressions.Regex.IsMatch(value, @"^[6-9]\d{9}$"); } // usage bool ok = "9876543210".IsIndianMobile(); Extension methods are static methods in a static class whose first parameter uses this, so they appear like instance methods.
04

Write a C# method to reverse a string without using Array.Reverse or LINQ.

Save to ▾
Show answer
static string ReverseText(string input) { char[] chars = input.ToCharArray(); int left = 0, right = chars.Length - 1; while (left < right) { (chars[left], chars[right]) = (chars[right], chars[left]); left++; right--; } return new string(chars); } Two pointers swap from both ends, giving O(n) time and O(n) space for the char array.
05

Show a class using a primary constructor with dependency injection.

Save to ▾
Show answer
public class OrderService(IOrderRepository repo, ILogger<OrderService> logger) { public async Task<Order?> GetAsync(int id) { logger.LogInformation("Fetching order {Id}", id); return await repo.FindAsync(id); } } Primary constructors on classes arrived in C# 12. Parameters are captured and usable in all members, removing boilerplate fields. They are not readonly, so assign to a readonly field if immutability matters.
06

Show an example of the Dependency Inversion Principle in C#.

OOP in C#Medium
Save to ▾
Show answer
public interface INotifier { Task SendAsync(string to, string msg); } public class SmsNotifier : INotifier { public Task SendAsync(string to, string msg) => Task.CompletedTask; // call SMS API } public class OrderService(INotifier notifier) { public Task ConfirmAsync(Order o) => notifier.SendAsync(o.Phone, "Order placed"); } // Program.cs builder.Services.AddScoped<INotifier, SmsNotifier>(); OrderService depends on the abstraction, so you can swap to email or a mock without changing it.
07

Show constructor chaining in C#.

Save to ▾
Show answer
public class Customer { public string Name { get; } public string City { get; } public Customer(string name) : this(name, "Unknown") { } public Customer(string name, string city) { Name = name; City = city; } } public class PremiumCustomer : Customer { public PremiumCustomer(string name) : base(name, "Delhi") { } } this() calls another constructor of the same class and base() calls the parent constructor, avoiding duplicated setup code.
08

Show encapsulation using properties, including init-only and validation.

Save to ▾
Show answer
public class BankAccount { public string AccountNo { get; init; } = ""; public decimal Balance { get; private set; } public void Deposit(decimal amount) { if (amount <= 0) throw new ArgumentOutOfRangeException(nameof(amount)); Balance += amount; } } var acc = new BankAccount { AccountNo = "SB1001" }; Balance can only change through Deposit, and AccountNo can be set only during object creation.
09

Show how Func, Action and Predicate are used.

OOP in C#Medium
Save to ▾
Show answer
Func<decimal, decimal> addGst = price => price * 1.18m; Action<string> log = msg => Console.WriteLine($"[LOG] {msg}"); Predicate<int> isAdult = age => age >= 18; decimal total = addGst(1000m); // 1180 log($"Total {total}"); bool ok = isAdult(21); // true Func returns a value (last type argument is the return type), Action returns void, and Predicate<T> returns bool. They save you from declaring custom delegate types.
10

Write a thread-safe singleton in C#.

Save to ▾
Show answer
public sealed class AppConfig { private static readonly Lazy<AppConfig> _instance = new(() => new AppConfig()); public static AppConfig Instance => _instance.Value; private AppConfig() { // load settings once } } Lazy<T> is thread-safe by default and creates the object only on first access. The private constructor and sealed class prevent other instances. In ASP.NET Core, prefer AddSingleton.
11

Using LINQ, group employees by department and get the count and average salary.

Save to ▾
Show answer
var report = employees .GroupBy(e => e.Department) .Select(g => new { Department = g.Key, Count = g.Count(), AvgSalary = g.Average(e => e.Salary) }) .OrderByDescending(x => x.AvgSalary) .ToList(); GroupBy returns groups with a Key, and aggregate methods run per group. With EF Core this translates to SQL GROUP BY.
12

Write a LINQ query that joins orders with customers and returns customer name and order total.

Save to ▾
Show answer
var result = orders .Join(customers, o => o.CustomerId, c => c.Id, (o, c) => new { c.Name, o.Total }) .ToList(); // query syntax var result2 = (from o in orders join c in customers on o.CustomerId equals c.Id select new { c.Name, o.Total }).ToList(); Join is an inner join. For a left join use GroupJoin with DefaultIfEmpty, or the LeftJoin operator added in .NET 10.
13

Find the second highest salary from a list using LINQ.

Save to ▾
Show answer
int? second = employees .Select(e => e.Salary) .Distinct() .OrderByDescending(s => s) .Skip(1) .Cast<int?>() .FirstOrDefault(); Distinct handles ties, so if two people earn the top salary the next lower value is returned. Casting to int? makes the result null instead of 0 when fewer than two distinct salaries exist.
14

Show how yield return works with an example.

Save to ▾
Show answer
static IEnumerable<int> EvenNumbers(int max) { for (int i = 0; i <= max; i += 2) { yield return i; // pause here, resume on next MoveNext } } foreach (var n in EvenNumbers(10).Take(3)) Console.WriteLine(n); // 0 2 4 The compiler builds a state machine, so values are produced lazily one at a time. Only three values are generated here, which saves memory for large or infinite sequences.
15

Show the newer LINQ methods Chunk, DistinctBy and MaxBy.

Save to ▾
Show answer
// split 1,000 ids into batches of 100 for bulk API calls foreach (int[] batch in ids.Chunk(100)) await SendBatchAsync(batch); // unique customers by email var unique = customers.DistinctBy(c => c.Email).ToList(); // highest-paid employee object, not just the salary Employee? top = employees.MaxBy(e => e.Salary); These were added in .NET 6 and remove the need for custom helpers or third-party libraries like MoreLINQ.
16

Sort a list of students by marks descending, then by name ascending.

Save to ▾
Show answer
var ranked = students .OrderByDescending(s => s.Marks) .ThenBy(s => s.Name) .ToList(); // in-place alternative with a comparison students.Sort((a, b) => b.Marks != a.Marks ? b.Marks.CompareTo(a.Marks) : string.Compare(a.Name, b.Name, StringComparison.Ordinal)); OrderBy is stable and returns a new sequence; List.Sort sorts in place and is not stable.
17

Show how Task.WhenAll and Task.WhenAny are used.

Save to ▾
Show answer
// run three independent calls in parallel var userTask = userApi.GetAsync(id); var ordersTask = orderApi.GetAsync(id); var walletTask = walletApi.GetAsync(id); await Task.WhenAll(userTask, ordersTask, walletTask); var dashboard = new Dashboard(userTask.Result, ordersTask.Result, walletTask.Result); // timeout using WhenAny var work = SlowCallAsync(); if (await Task.WhenAny(work, Task.Delay(2000)) != work) throw new TimeoutException(); WhenAll completes when all finish; WhenAny returns the first task to finish.
18

How do you use CancellationToken in an ASP.NET Core API?

Save to ▾
Show answer
[HttpGet("report")] public async Task<IActionResult> Report(CancellationToken ct) { var rows = await _db.Sales .Where(s => s.Year == 2026) .ToListAsync(ct); await _http.PostAsJsonAsync("/audit", rows.Count, ct); return Ok(rows); } ASP.NET Core binds the token to HttpContext.RequestAborted, so if the user closes the browser the token is cancelled and EF Core and HttpClient stop work, saving database and CPU time.
19

Demonstrate a race condition on a counter and fix it.

Save to ▾
Show answer
int count = 0; Parallel.For(0, 100_000, _ => count++); Console.WriteLine(count); // often less than 100000 int safe = 0; Parallel.For(0, 100_000, _ => Interlocked.Increment(ref safe)); Console.WriteLine(safe); // always 100000 count++ is a read, add and write, so two threads can read the same value and lose an update. Interlocked performs the increment atomically without a full lock.
20

Limit concurrent calls to a third-party API to 5 at a time using SemaphoreSlim.

Save to ▾
Show answer
private static readonly SemaphoreSlim _gate = new(5); public async Task<string> CallAsync(string url) { await _gate.WaitAsync(); try { return await _http.GetStringAsync(url); } finally { _gate.Release(); } } var results = await Task.WhenAll(urls.Select(CallAsync)); SemaphoreSlim supports async waiting, unlike lock. The finally block guarantees the slot is released even when a call fails.
21

Show how to stream data with IAsyncEnumerable.

Save to ▾
Show answer
public async IAsyncEnumerable<Order> GetOrdersAsync( [EnumeratorCancellation] CancellationToken ct = default) { await foreach (var o in _db.Orders.AsNoTracking().AsAsyncEnumerable().WithCancellation(ct)) yield return o; } // consumer await foreach (var order in service.GetOrdersAsync()) Console.WriteLine(order.Id); Items are produced and consumed one at a time asynchronously. ASP.NET Core can stream an IAsyncEnumerable result as JSON without buffering the whole list.
22

Write a BackgroundService that cleans expired OTPs every 5 minutes.

Save to ▾
Show answer
public class OtpCleanupService(IServiceScopeFactory scopes) : BackgroundService { protected override async Task ExecuteAsync(CancellationToken ct) { using var timer = new PeriodicTimer(TimeSpan.FromMinutes(5)); while (await timer.WaitForNextTickAsync(ct)) { using var scope = scopes.CreateScope(); var db = scope.ServiceProvider.GetRequiredService<AppDbContext>(); await db.Otps.Where(o => o.ExpiresAt < DateTime.UtcNow).ExecuteDeleteAsync(ct); } } } // builder.Services.AddHostedService<OtpCleanupService>(); A scope is created because DbContext is scoped while hosted services are singletons.
23

Write custom middleware that logs how long each request takes.

Save to ▾
Show answer
public class TimingMiddleware(RequestDelegate next, ILogger<TimingMiddleware> logger) { public async Task InvokeAsync(HttpContext context) { var sw = Stopwatch.StartNew(); await next(context); sw.Stop(); logger.LogInformation("{Method} {Path} -> {Status} in {Ms} ms", context.Request.Method, context.Request.Path, context.Response.StatusCode, sw.ElapsedMilliseconds); } } // Program.cs app.UseMiddleware<TimingMiddleware>(); Code before next runs on the request, code after it runs on the response.
24

Show attribute routing for a products controller with route constraints.

Save to ▾
Show answer
[ApiController] [Route("api/[controller]")] public class ProductsController(IProductService service) : ControllerBase { [HttpGet] public async Task<IActionResult> GetAll() => Ok(await service.GetAllAsync()); [HttpGet("{id:int}")] public async Task<IActionResult> Get(int id) { var p = await service.GetAsync(id); return p is null ? NotFound() : Ok(p); } [HttpPost] public async Task<IActionResult> Create(ProductDto dto) { var created = await service.CreateAsync(dto); return CreatedAtAction(nameof(Get), new { id = created.Id }, created); } }
25

Implement global exception handling that returns ProblemDetails.

Save to ▾
Show answer
public class GlobalExceptionHandler(ILogger<GlobalExceptionHandler> logger) : IExceptionHandler { public async ValueTask<bool> TryHandleAsync(HttpContext ctx, Exception ex, CancellationToken ct) { logger.LogError(ex, "Unhandled error"); var status = ex is KeyNotFoundException ? 404 : 500; ctx.Response.StatusCode = status; await ctx.Response.WriteAsJsonAsync(new ProblemDetails { Status = status, Title = status == 404 ? "Not found" : "Server error" }, ct); return true; } } // Program.cs builder.Services.AddExceptionHandler<GlobalExceptionHandler>(); builder.Services.AddProblemDetails(); app.UseExceptionHandler();
26

Configure JWT bearer authentication in an ASP.NET Core API.

Save to ▾
Show answer
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) .AddJwtBearer(o => { o.TokenValidationParameters = new TokenValidationParameters { ValidateIssuer = true, ValidateAudience = true, ValidateLifetime = true, ValidateIssuerSigningKey = true, ValidIssuer = builder.Configuration["Jwt:Issuer"], ValidAudience = builder.Configuration["Jwt:Audience"], IssuerSigningKey = new SymmetricSecurityKey( Encoding.UTF8.GetBytes(builder.Configuration["Jwt:Key"]!)) }; }); builder.Services.AddAuthorization(); app.UseAuthentication(); app.UseAuthorization(); Then protect endpoints with [Authorize] or [Authorize(Roles = "Admin")].
27

Show how to bind configuration from appsettings.json using the Options pattern.

Save to ▾
Show answer
// appsettings.json // "Smtp": { "Host": "smtp.example.com", "Port": 587 } public class SmtpOptions { public string Host { get; set; } = ""; public int Port { get; set; } } builder.Services.Configure<SmtpOptions>(builder.Configuration.GetSection("Smtp")); public class EmailService(IOptions<SmtpOptions> options) { private readonly SmtpOptions _smtp = options.Value; } appsettings.{Environment}.json and environment variables override base values. Use IOptionsMonitor to pick up changes without restart.
28

Add rate limiting to a login endpoint in ASP.NET Core.

Save to ▾
Show answer
builder.Services.AddRateLimiter(o => { o.RejectionStatusCode = StatusCodes.Status429TooManyRequests; o.AddPolicy("login", ctx => RateLimitPartition.GetFixedWindowLimiter( ctx.Connection.RemoteIpAddress?.ToString() ?? "unknown", _ => new FixedWindowRateLimiterOptions { PermitLimit = 5, Window = TimeSpan.FromMinutes(1) })); }); app.UseRateLimiter(); app.MapPost("/api/login", LoginHandler).RequireRateLimiting("login"); Each IP gets 5 attempts per minute, which slows brute-force attacks. Behind a proxy, use the forwarded client IP.
29

Which commands do you use to create and apply EF Core migrations?

Save to ▾
Show answer
dotnet tool install --global dotnet-ef # create a migration from model changes dotnet ef migrations add AddOrderStatus # apply pending migrations to the database dotnet ef database update # undo the last unapplied migration dotnet ef migrations remove # generate an idempotent SQL script for production dotnet ef migrations script --idempotent -o deploy.sql In Visual Studio the Package Manager Console equivalents are Add-Migration and Update-Database.
30

Configure a one-to-many relationship between Customer and Order using the Fluent API.

Save to ▾
Show answer
public class Customer { public int Id { get; set; } public List<Order> Orders { get; set; } = []; } public class Order { public int Id { get; set; } public int CustomerId { get; set; } public Customer Customer { get; set; } = null!; } protected override void OnModelCreating(ModelBuilder mb) { mb.Entity<Order>() .HasOne(o => o.Customer) .WithMany(c => c.Orders) .HasForeignKey(o => o.CustomerId) .OnDelete(DeleteBehavior.Restrict); mb.Entity<Order>().Property(o => o.Total).HasPrecision(18, 2); } Restrict prevents deleting a customer who still has orders.
31

How do you run raw SQL safely in EF Core?

Save to ▾
Show answer
// entity query with parameters (interpolation becomes SqlParameter) var orders = await db.Orders .FromSql($"SELECT * FROM Orders WHERE City = {city}") .Where(o => o.Total > 1000) .ToListAsync(); // non-entity results var totals = await db.Database .SqlQuery<decimal>($"SELECT SUM(Total) AS Value FROM Orders") .ToListAsync(); // stored procedure await db.Database.ExecuteSqlAsync($"EXEC usp_CloseMonth {month}"); Never build SQL by string concatenation; FromSqlRaw with concatenated input invites SQL injection.
32

Show bulk update and delete with ExecuteUpdate and ExecuteDelete.

Save to ▾
Show answer
// mark all unpaid invoices older than 30 days as overdue int updated = await db.Invoices .Where(i => !i.IsPaid && i.DueDate < DateTime.UtcNow.AddDays(-30)) .ExecuteUpdateAsync(s => s .SetProperty(i => i.Status, "Overdue") .SetProperty(i => i.UpdatedAt, DateTime.UtcNow)); // delete old logs int deleted = await db.AuditLogs .Where(l => l.CreatedAt < cutoff) .ExecuteDeleteAsync(); These run a single SQL UPDATE or DELETE without loading entities, available since EF Core 7. They bypass the change tracker.
33

How do you use an explicit transaction in EF Core across multiple SaveChanges calls?

Save to ▾
Show answer
await using var tx = await db.Database.BeginTransactionAsync(); try { db.Orders.Add(order); await db.SaveChangesAsync(); var stock = await db.Stocks.SingleAsync(s => s.ProductId == order.ProductId); stock.Quantity -= order.Quantity; await db.SaveChangesAsync(); await tx.CommitAsync(); } catch { await tx.RollbackAsync(); throw; } A single SaveChanges is already transactional; explicit transactions are needed when you combine several saves or raw SQL into one unit.
34

Implement soft delete with a global query filter.

Save to ▾
Show answer
public class Product { public int Id { get; set; } public bool IsDeleted { get; set; } } protected override void OnModelCreating(ModelBuilder mb) { mb.Entity<Product>().HasQueryFilter(p => !p.IsDeleted); } public override Task<int> SaveChangesAsync(CancellationToken ct = default) { foreach (var e in ChangeTracker.Entries<Product>().Where(e => e.State == EntityState.Deleted)) { e.State = EntityState.Modified; e.Entity.IsDeleted = true; } return base.SaveChangesAsync(ct); } Every query now hides deleted rows automatically; use IgnoreQueryFilters() for admin screens.
35

Implement paging for a product list in EF Core.

Save to ▾
Show answer
public async Task<PagedResult<ProductDto>> GetPageAsync(int page, int size) { var query = db.Products.AsNoTracking().OrderBy(p => p.Id); int total = await query.CountAsync(); var items = await query .Skip((page - 1) * size) .Take(size) .Select(p => new ProductDto(p.Id, p.Name, p.Price)) .ToListAsync(); return new PagedResult<ProductDto>(items, total, page, size); } Always order before Skip and Take. For very deep pages, keyset paging with Where(p => p.Id > lastId) is faster than large offsets.
36

Write a SQL Server query to find the second highest salary.

Save to ▾
Show answer
-- using DENSE_RANK (handles ties) SELECT Salary FROM ( SELECT Salary, DENSE_RANK() OVER (ORDER BY Salary DESC) AS rnk FROM Employees ) t WHERE rnk = 2; -- using OFFSET SELECT DISTINCT Salary FROM Employees ORDER BY Salary DESC OFFSET 1 ROW FETCH NEXT 1 ROW ONLY; Change 2 to N for the Nth highest salary.
37

Write a query to find duplicate email addresses and delete the extra rows, keeping the lowest Id.

Save to ▾
Show answer
-- find duplicates SELECT Email, COUNT(*) AS Cnt FROM Users GROUP BY Email HAVING COUNT(*) > 1; -- delete duplicates, keep lowest Id WITH d AS ( SELECT Id, ROW_NUMBER() OVER (PARTITION BY Email ORDER BY Id) AS rn FROM Users ) DELETE FROM d WHERE rn > 1; After cleanup, add a unique index on Email to stop duplicates returning.
38

Show the difference between ROW_NUMBER, RANK and DENSE_RANK with a query.

Save to ▾
Show answer
SELECT Name, Department, Salary, ROW_NUMBER() OVER (PARTITION BY Department ORDER BY Salary DESC) AS RowNum, RANK() OVER (PARTITION BY Department ORDER BY Salary DESC) AS Rnk, DENSE_RANK() OVER (PARTITION BY Department ORDER BY Salary DESC) AS DenseRnk FROM Employees; -- salaries 90, 90, 80 give -- ROW_NUMBER: 1, 2, 3 -- RANK: 1, 1, 3 -- DENSE_RANK: 1, 1, 2 PARTITION BY restarts numbering for each department.
39

Write a recursive CTE that lists an employee hierarchy with levels.

Save to ▾
Show answer
WITH Org AS ( SELECT Id, Name, ManagerId, 0 AS Lvl FROM Employees WHERE ManagerId IS NULL -- anchor: CEO UNION ALL SELECT e.Id, e.Name, e.ManagerId, o.Lvl + 1 FROM Employees e JOIN Org o ON e.ManagerId = o.Id -- recursive part ) SELECT REPLICATE(' ', Lvl) + Name AS Hierarchy, Lvl FROM Org OPTION (MAXRECURSION 100); The anchor query runs once and the recursive part repeats until no new rows are found.
40

Write a stored procedure that transfers money between accounts with TRY-CATCH and a transaction.

Save to ▾
Show answer
CREATE OR ALTER PROCEDURE usp_Transfer @From INT, @To INT, @Amt DECIMAL(18,2) AS BEGIN SET NOCOUNT ON; SET XACT_ABORT ON; BEGIN TRY BEGIN TRAN; UPDATE Accounts SET Balance = Balance - @Amt WHERE Id = @From AND Balance >= @Amt; IF @@ROWCOUNT = 0 THROW 50001, 'Insufficient balance', 1; UPDATE Accounts SET Balance = Balance + @Amt WHERE Id = @To; COMMIT; END TRY BEGIN CATCH IF @@TRANCOUNT > 0 ROLLBACK; THROW; END CATCH END
41

Write an Angular HTTP interceptor that adds a JWT to every API request.

Save to ▾
Show answer
import { HttpInterceptorFn } from '@angular/common/http'; import { inject } from '@angular/core'; export const authInterceptor: HttpInterceptorFn = (req, next) => { const token = inject(AuthService).token(); if (token) { req = req.clone({ setHeaders: { Authorization: `Bearer ${token}` } }); } return next(req); }; // app.config.ts provideHttpClient(withInterceptors([authInterceptor])); Requests are immutable, so clone() creates a modified copy. The ASP.NET Core JWT middleware then reads the header.
42

Protect an Angular route so only logged-in users can open it.

Save to ▾
Show answer
import { CanActivateFn, Router } from '@angular/router'; import { inject } from '@angular/core'; export const authGuard: CanActivateFn = () => { const auth = inject(AuthService); return auth.isLoggedIn() ? true : inject(Router).createUrlTree(['/login']); }; // app.routes.ts export const routes = [ { path: 'dashboard', component: DashboardComponent, canActivate: [authGuard] }, { path: 'login', component: LoginComponent } ]; Guards only improve user experience; the API must still enforce [Authorize] on the server.
43

Show the useState and useEffect hooks in a React component.

Save to ▾
Show answer
import { useState, useEffect } from 'react'; export function Timer() { const [seconds, setSeconds] = useState(0); useEffect(() => { const id = setInterval(() => setSeconds(s => s + 1), 1000); return () => clearInterval(id); // cleanup on unmount }, []); // empty array: run once return <p>Elapsed: {seconds}s</p>; } useState stores state that triggers re-render; useEffect runs side effects after render, and its dependency array controls when it re-runs.
44

Fetch products from an ASP.NET Core API in React with loading and error states.

Save to ▾
Show answer
function Products() { const [items, setItems] = useState([]); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); useEffect(() => { const ctrl = new AbortController(); fetch('/api/products', { signal: ctrl.signal }) .then(r => { if (!r.ok) throw new Error(r.status); return r.json(); }) .then(setItems) .catch(e => { if (e.name !== 'AbortError') setError(e.message); }) .finally(() => setLoading(false)); return () => ctrl.abort(); }, []); if (loading) return <p>Loading...</p>; if (error) return <p>Error: {error}</p>; return <ul>{items.map(p => <li key={p.id}>{p.name}</li>)}</ul>; }

Frequently asked questions

Why are practical questions important?

Most technical rounds include at least one live task. Practising the exact typing and reasoning makes you calm and fast in the real round.

How should I answer them?

Talk while you work: say your approach first, write the simplest correct version, then improve it and mention edge cases.