Phỏng vấn English

Technical Q và A — Sample answers in English

30+ technical questions in English với sample answer, hint phát âm, follow-up câu hỏi.
Cách dùng: đọc to câu hỏi → bấm giờ 60 giây → tự trả lời thành tiếng → sau đó đọc sample. Không học thuộc — chỉ học structurekeyword.

A. C# Fundamentals

1. What's the difference between value types and reference types?

Sample answer:

Value types like int, bool, or any struct are stored directly on the stack and hold their actual value. Reference types like class, string, or arrays live on the heap, and the variable just holds a pointer to them.

When you assign one variable to another, value types copy the actual value, but reference types copy the reference — so two variables point to the same object. A good example is that modifying an array through one variable will affect the other.

Keyword: stack, heap, pointer, copy by value vs by reference.

Follow-up: "Is string a value or reference type?" → reference but immutable, behaves like value.


2. Explain boxing and unboxing.

Sample answer:

Boxing is when a value type gets wrapped into an object reference, which allocates on the heap. Unboxing is the reverse — you explicitly cast the object back to the value type.

The performance cost is real, especially in tight loops, so I avoid it by using generic collections like List<int> instead of the old ArrayList.


3. What does "immutable" mean? Why does it matter for strings?

Sample answer:

Immutable means an object's state can't change after it's created. With string, every operation like concatenation actually creates a new string. So if you concatenate inside a loop 10,000 times, you'll create 10,000 string objects and put pressure on the garbage collector.

That's why we use StringBuilder for repeated modifications — it uses a mutable internal buffer and appends in amortized constant time.


4. What is the difference between const and readonly?

Sample answer:

const is a compile-time constant — its value gets embedded into the calling code, so if you change it you have to rebuild every consumer. It also only works for primitives.

readonly is set at runtime, usually in the constructor, and each instance can have its own value. static readonly lives at the class level and gets set once when the class is loaded.


5. What happens when you write throw ex versus just throw?

Sample answer:

throw rethrows the exception while preserving the original stack trace, so you can still trace where the error happened. throw ex resets the stack trace to the current line, which loses crucial debugging information. So in practice, I always use bare throw unless I'm explicitly wrapping the exception with throw new SomethingElse("...", ex).


B. OOP & SOLID

6. Can you walk me through the four pillars of OOP with an example?

Sample answer:

Sure. The four pillars are encapsulation, abstraction, inheritance, and polymorphism.

Encapsulation is about hiding internal state behind a public interface — for example, a BankAccount class exposes a Deposit method instead of letting outside code modify the balance directly.

Abstraction focuses on what something does rather than how — like an IRepository interface that doesn't reveal whether the data comes from SQL or a file.

Inheritance lets a derived class reuse code from a base class — like Dog extending Animal.

Polymorphism lets you treat different concrete types through a common base — so I can have Animal[] zoo containing Dog and Cat, and calling Speak() invokes the right override at runtime.


7. Interface versus abstract class — when do you choose which?

Sample answer:

An interface defines a contract — what a type can do — without state or implementation. A class can implement multiple interfaces, so I use them to describe capabilities like IDisposable or IComparable.

An abstract class is more like a partial implementation. It can hold state, have constructors, and provide concrete methods. I use it when several classes truly share both behavior and identity — for example, a base Repository<T> with common query helpers.

In modern .NET I tend to default to interfaces because they're easier to mock for unit testing.


8. Explain the SOLID principles.

Sample answer (compressed):

SOLID is an acronym for five OOP design principles.

S is Single Responsibility — a class should have only one reason to change.

O is Open/Closed — open for extension, closed for modification. You should be able to add new behavior without editing existing code.

L is Liskov Substitution — subclasses should be usable in place of their base class without breaking the program.

I is Interface Segregation — many small, specific interfaces are better than one fat one, so clients don't depend on methods they don't use.

D is Dependency Inversion — high-level modules shouldn't depend on low-level modules; both should depend on abstractions. In ASP.NET Core, this is implemented through built-in dependency injection.


9. What is Dependency Injection and why do we use it?

Sample answer:

Dependency Injection is a technique where a class receives its dependencies from outside instead of creating them itself. Typically through constructor injection.

The main benefits are testability — I can pass in mocks during unit tests — and flexibility, because I can swap implementations without changing the consumer. ASP.NET Core has a built-in DI container, so I register services in Program.cs and the framework wires them automatically.


10. What's the difference between Singleton, Scoped, and Transient lifetimes?

Sample answer:

Singleton creates one instance for the entire application lifetime — good for stateless services, caches, or loggers.

Scoped creates one instance per HTTP request — that's the right lifetime for DbContext because we want all operations within a single request to share the same unit of work.

Transient creates a new instance every time it's injected. I use it for lightweight, stateless helpers.

A common pitfall is injecting a scoped service into a singleton, which causes a captive dependency.


C. Async & Performance

11. How does async/await actually work?

Sample answer:

A lot of people think async/await creates a new thread, but it doesn't. When the runtime hits an await, the method returns a Task and releases the current thread back to the pool. Once the awaited operation completes — typically I/O like an HTTP call or a database query — the continuation gets scheduled to run, possibly on a different thread.

So async/await is really about freeing threads during I/O, not parallelism. For CPU-bound work, you'd use Task.Run to offload to the thread pool.


12. Why should you avoid .Result or .Wait() on a Task?

Sample answer:

Calling .Result or .Wait() blocks the calling thread until the task completes. In environments with a synchronization context, like classic ASP.NET or WPF, this can cause a deadlock because the continuation tries to resume on the original thread, which is blocked.

In ASP.NET Core there's no SynchronizationContext, so it's less catastrophic, but it still wastes a thread. The right approach is await all the way up.


13. What's the difference between IEnumerable and IQueryable?

Sample answer:

IEnumerable represents an in-memory collection — when you apply LINQ operations, they execute on the client side.

IQueryable builds an expression tree that gets translated into the underlying query language, like SQL for EF Core. So if I filter an IQueryable with .Where, that filter gets pushed down to the database.

The mistake is calling .ToList() too early, which materializes everything into memory and turns subsequent operations into client-side work.


D. Database & SQL

14. Explain INNER JOIN, LEFT JOIN, and when you'd use each.

Sample answer:

An INNER JOIN returns only rows that match in both tables, so it's good when you only care about records that have a relationship — for example, all orders along with the customer who placed them, assuming every order has a customer.

A LEFT JOIN returns all rows from the left table plus matching rows from the right, with NULL where there's no match. I use this when I want to keep all records from one side, like all customers including those who haven't placed any orders yet.


15. What is an index and when would you avoid creating one?

Sample answer:

An index is an auxiliary data structure, usually a B-tree, that the database uses to find rows quickly without scanning the whole table. The trade-off is that indexes take space and slow down inserts and updates because the index also needs to be maintained.

So I'd avoid indexing columns that change very frequently, columns with low selectivity like a Gender field with two values, and small tables where a full scan is already fast.


16. What is database normalization?

Sample answer:

Normalization is the process of organizing tables to reduce redundancy and prevent anomalies during insert, update, or delete.

First normal form requires atomic values — no arrays or repeating groups in one column. Second normal form removes partial dependencies on a composite key. Third normal form removes transitive dependencies, where a non-key column depends on another non-key column.

In practice, I aim for third normal form by default, but for reporting workloads I might denormalize to avoid expensive joins.


17. What does ACID stand for?

Sample answer:

ACID describes the guarantees of a transactional database.

Atomicity — all operations in a transaction succeed together or roll back together.

Consistency — the database moves from one valid state to another, respecting all constraints.

Isolation — concurrent transactions don't interfere with each other's intermediate state.

Durability — once committed, the data persists even if the system crashes.


E. ASP.NET Core & Web API

18. Walk me through what happens in the ASP.NET Core request pipeline.

Sample answer:

When a request comes in, Kestrel — the built-in web server — passes it through a chain of middleware components. Each middleware can inspect the request, do some work, and either call the next middleware or short-circuit the pipeline.

The typical order is exception handling, HTTPS redirection, static files, routing, CORS, authentication, authorization, and finally endpoint execution — which is where my controller method runs. The order matters; for example, authentication must come before authorization.


19. Which HTTP methods are idempotent?

Sample answer:

Idempotent means calling the method multiple times has the same effect as calling it once. GET, PUT, DELETE, HEAD, and OPTIONS are idempotent by definition. POST is not, because each call typically creates a new resource. PATCH isn't strictly idempotent by spec, but it's good practice to design PATCH endpoints to be idempotent when possible.


20. What's the difference between authentication and authorization?

Sample answer:

Authentication answers "who are you" — it verifies the identity of the user, usually through credentials or a token. Authorization answers "what are you allowed to do" — it checks whether the authenticated user has permission for the requested action, often based on roles or claims.

In ASP.NET Core, UseAuthentication must be registered before UseAuthorization because authorization checks the identity that authentication populated.


21. What status code would you return when a POST succeeds?

Sample answer:

The standard is 201 Created, with a Location header pointing to the new resource's URI, and the response body containing the created resource. In ASP.NET Core I usually use CreatedAtAction(nameof(Get), new { id = ... }, dto) which sets all of that automatically.


22. How does JWT-based authentication work?

Sample answer:

A JWT is a token that contains three parts — header, payload, and signature — encoded in base64URL and separated by dots. The payload holds claims like the user ID, roles, and expiration time. The signature is a hash that proves the token wasn't tampered with.

The flow is: the client logs in with credentials, the server issues a JWT, and the client sends it in the Authorization header on every subsequent request. The server verifies the signature and trusts the claims. It's stateless, so no session storage on the server side.


F. Entity Framework Core

23. What is the DbContext and why is it registered as Scoped?

Sample answer:

The DbContext is essentially a unit of work for a single business operation. It tracks entity changes and translates them to SQL when I call SaveChanges.

I register it as Scoped because we want one DbContext per HTTP request, so all operations within that request share the same change tracker and can be committed together. It's also not thread-safe, so reusing it across requests would cause race conditions.


24. What is the N+1 query problem?

Sample answer:

N+1 happens when you load a list of N parent entities with one query, then access a navigation property in a loop, which triggers N additional queries — one for each parent.

For example, loading 100 users and then accessing user.Orders for each one results in 101 queries. The fix is eager loading with .Include, or better, projecting directly to a DTO with .Select so EF generates a single optimized query.


25. When would you use .AsNoTracking()?

Sample answer:

I use AsNoTracking for read-only queries that don't need to update the database. By default, EF Core tracks every entity it materializes, which costs memory and CPU. Disabling tracking can give a 20–30% speed boost for queries that just return data to the UI.


G. Coding scenario

26. Given an array of integers, return indices of two numbers that add up to a target.

Sample answer (talking through it):

Okay, the brute-force approach is two nested loops, but that's O(n²). A better solution uses a hash map. I iterate through the array, and for each element I check if target - current is already in the map. If it is, I have my pair. If not, I store the current value and index in the map.

That gives me O(n) time and O(n) space, which is the standard answer for this problem.

public int[] TwoSum(int[] nums, int target) {
    var map = new Dictionary<int, int>();
    for (int i = 0; i < nums.Length; i++) {
        int need = target - nums[i];
        if (map.TryGetValue(need, out int j)) return new[] { j, i };
        map[nums[i]] = i;
    }
    return Array.Empty<int>();
}

Follow-up: "What if the array is sorted?" → two pointers, O(1) space.


27. Write a method to check if a string is a palindrome.

Sample explanation:

I'll use two pointers — one at the start and one at the end — moving toward the middle, comparing characters. If any pair doesn't match, return false. The time complexity is O(n), space is O(1).

public bool IsPalindrome(string s) {
    int l = 0, r = s.Length - 1;
    while (l < r) {
        if (char.ToLower(s[l]) != char.ToLower(s[r])) return false;
        l++; r--;
    }
    return true;
}

Follow-up: "What if there are spaces or punctuation?" → skip non-alphanumeric chars in the loop.


28. Reverse a linked list in place.

Sample explanation:

I'll iterate with three pointers: previous, current, and next. At each step I save the next node, point current's Next back to previous, then advance previous and current forward.

public ListNode? Reverse(ListNode? head) {
    ListNode? prev = null;
    var curr = head;
    while (curr != null) {
        var nxt = curr.Next;
        curr.Next = prev;
        prev = curr;
        curr = nxt;
    }
    return prev;
}

H. System & process

29. How would you debug a slow API endpoint?

Sample answer:

First, I'd reproduce the issue and measure — use Stopwatch around suspected code, or built-in profiling tools like dotTrace or MiniProfiler. I'd check the database query plan if it's a data-access issue, look for N+1 patterns, and verify indexes are being used.

If it's not a database issue, I'd check external calls — slow HTTP dependencies, missing async, or contention on shared resources. Logs and APM tools like Application Insights help spot patterns. The key is to isolate the bottleneck before optimizing.


30. How do you handle a code review where the reviewer disagrees with you?

Sample answer:

I try to listen first and understand their reasoning — they often have context I don't. If I still disagree after that, I'll explain my position with concrete trade-offs, maybe even a small experiment or benchmark. Code review is about the code, not the person, so I keep the tone neutral.

If we still can't agree, I defer to the more senior person or escalate to the team lead. As a fresher, I see reviews as one of the fastest ways to learn.


31. Tell me about a bug you found that was particularly tricky.

Sample STAR answer:

(Situation) In my school project, the dashboard page took about three seconds to load even though the dataset was small.

(Task) My job was to figure out why.

(Action) I added Stopwatch logging and noticed the EF Core query was firing 50 times instead of once. I realized I was looping through Orders and accessing order.Customer.Name inside the loop, which triggered lazy loading on each iteration. I switched to .Include(o => o.Customer) and also added a .Select projection to grab only the columns I needed.

(Result) The page load time dropped from 3 seconds to about 150 milliseconds. I learned to watch for N+1 patterns and to profile early.


© 2026 .NET Fresher Guide. All rights reserved.

Về Trang Web

Hướng dẫn toàn diện để chuẩn bị phỏng vấn vị trí .NET Fresher với nội dung từ lý thuyết đến thực hành.