C# 7.2中使用in方法参数是否存在弊端?为何不建议全方法标记in?
in in C# 7.2 Great question! It’s easy to see the appeal of in parameters—they help avoid copying large structs, and as you noted, can reduce stack pressure in recursive scenarios. But applying them universally comes with several downsides that make this practice a bad idea. Let’s break them down:
1. Semantic Confusion
The in modifier carries a clear semantic meaning: "this is a read-only reference to a value type, used to avoid expensive copies". If you slap in on every parameter (even small ones like int or DateTime), you’re diluting that meaning. Other developers reading your code will wonder:
- Is this parameter a large struct that needs copy avoidance?
- Is there a specific reason we can’t modify this value?
This ambiguity makes your code harder to understand and maintain, as the intent behind each parameter becomes unclear.
2. Performance Can Actually Decrease
For small value types (think 4-8 bytes, like int, float, or Guid), copying the value directly is cheaper than passing a reference via in. Here’s why:
- Copying a small value is a single CPU operation that fits perfectly in cache.
- Using
inrequires indirection (dereferencing a pointer to access the value), which adds overhead and can miss cache hits.
In these cases, in doesn’t just fail to help—it actively makes your code slower.
3. Restricts Future Flexibility
in parameters are read-only at the call site, and the compiler enforces that you can’t modify the parameter (or its members, if it’s a struct) inside the method. If your requirements change later—say, you need to tweak a local copy of the parameter—you’ll have to:
- Remove the
inmodifier (breaking any callers that rely on the read-only contract), or - Explicitly copy the
inparameter to a local variable before modifying it, adding unnecessary boilerplate.
This inflexibility can turn a small code change into a bigger hassle than needed.
4. Overload Resolution Headaches
Adding in to parameters can complicate method overloading. For example, if you have two methods:
void Process(int value) void Process(in int value)
Calling Process(42) will trigger a compiler error because the call is ambiguous. You’d have to explicitly specify in (like Process(in 42)) to resolve it, which makes your code more verbose and error-prone.
5. Stack Overflow Misconception
You’re right that in can reduce stack usage for large structs in recursive calls, but this benefit only applies to large value types. For small structs or value types, the stack space saved is negligible—stack overflow is almost always caused by excessive recursion depth, not the size of individual parameters. Applying in everywhere won’t fix a recursion depth issue, but it will introduce the other problems listed above.
When Should You Use in?
Reserve in for large structs (roughly 16 bytes or more, depending on your CPU architecture) where:
- You don’t need to modify the parameter, and
- The cost of copying the struct outweighs the overhead of indirection.
For small value types or reference types, in provides no meaningful benefit and should be avoided.
内容的提问来源于stack exchange,提问作者Filip Cordas

