A common shorthand — "value types live on the stack, reference types live on the heap" — is a useful first approximation but not actually the rule the C# spec makes, and it's worth understanding precisely because interviewers often probe the exact boundary.
The real rule: a value type's storage lives wherever the variable holding it lives. A local variable inside a method typically lives on the stack — so a local int or struct does too. But a value type that's a field of a class lives on the heap, because it's stored inline as part of that class instance's allocation:
class Container
{
public int Number; // this int lives on the heap, inline inside the Container object
}
void Method()
{
int local = 5; // lives on the stack
var container = new Container(); // the Container object lives on the heap
container.Number = 10; // this int is part of that heap allocation, not on the stack
}
Similarly, a local variable captured by a lambda or used in an async method (both of which need to survive past the current stack frame) gets compiler-generated storage on the heap regardless of whether its type is a value type or reference type. The stack/heap distinction is an implementation detail of where memory happens to live; the value-vs-reference distinction is about copy vs. share semantics on assignment. They correlate strongly for simple local variables, which is where the shorthand comes from, but they are not the same axis, and conflating them leads to wrong predictions in the cases above.