Caller Info Param Last
ID |
csharp.caller_info_param_last |
Severity |
high |
Remediation Complexity |
trivial |
Remediation Risk |
low |
Remediation Effort |
low |
Resource |
Best Practice |
Language |
CSharp |
Tags |
api_design, attributes, best_practice, parameters |
Description
Reports a parameter carrying one of the caller-information attributes — CallerFilePath,
CallerLineNumber, CallerMemberName or CallerArgumentExpression — that is followed by a
parameter carrying none of them. Both the plain and the Attribute-suffixed spelling are
recognised, qualified or not.
Put differently: the caller-information parameters must form the tail of the parameter list.
Rationale
A caller-information attribute is a compile-time favour done to the caller. When the argument is left out, the compiler writes the call site’s own file path, line number, member name or argument text in its place. When the argument is supplied, the attribute is ignored — there is nothing left to fill in.
That makes the position of such a parameter part of its contract. Everything before it has to be written out at the call site, so a caller-information parameter in the middle of the list can only be skipped by naming the arguments that come after it:
using System.Runtime.CompilerServices;
public class Tracer
{
public void Log([CallerMemberName] string member = "", string message = "") { } // FLAW
public void Report(string message, [CallerMemberName] string member = "") { } // OK
}
// tracer.Log(message: "started"); the only way to let 'member' be filled in
// tracer.Log("started"); compiles, and quietly lands in 'member'
The second call is the one that hurts: it compiles, it looks right, and the message ends up in the
parameter that was supposed to record where the call came from — while message takes the empty
default. Nothing reports the mistake, and the diagnostic value the parameter was added for is gone.
Remediation
Move every caller-information parameter to the end of the list, after all parameters callers are expected to pass. They already need a default value to be omittable, so the ordering rule for optional parameters is satisfied at the same time. If an existing signature cannot be reordered because callers depend on the current positions, add an overload with the parameters in the right order and leave the old one to delegate to it.