== Why is this an issue?

https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/attributes/caller-information[Caller information attributes] provide a way to get information about the caller of a method through https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/named-and-optional-arguments#optional-arguments[optional] parameters. But they only work right if their values aren't provided explicitly. So if you define a method with caller info attributes in the middle of the parameter list, the caller is forced to use named arguments if they want to use the method properly.

This rule raises an issue when the following attributes are used on parameters before the end of the parameter list:

* https://learn.microsoft.com/en-us/dotnet/api/system.runtime.compilerservices.callerfilepathattribute[CallerFilePathAttribute]
* https://learn.microsoft.com/en-us/dotnet/api/system.runtime.compilerservices.callerlinenumberattribute[CallerLineNumberAttribute]
* https://learn.microsoft.com/en-us/dotnet/api/system.runtime.compilerservices.callermembernameattribute[CallerMemberNameAttribute]
* https://learn.microsoft.com/en-us/dotnet/api/system.runtime.compilerservices.callerargumentexpressionattribute[CallerArgumentExpressionAttribute]

== How to fix it

Move the decorated parameters to the end of the parameter list.

=== Code examples

==== Noncompliant code example

[source,csharp,diff-id=1,diff-type=noncompliant]
----
void TraceMessage([CallerMemberName] string memberName = "",
  [CallerFilePath] string filePath = "",
  [CallerLineNumber] int lineNumber = 0,
  string message = null)  // Noncompliant: decorated parameters appear before "message" parameter
{
  /* ... */
}
----

==== Compliant solution

[source,csharp,diff-id=1,diff-type=compliant]
----
void TraceMessage(string message = null,
  [CallerMemberName] string memberName = "",
  [CallerFilePath] string filePath = "",
  [CallerLineNumber] int lineNumber = 0)
{
  /* ... */
}
----

== Resources

=== Documentation

* https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/attributes/caller-information[Determine caller information using attributes interpreted by the C# compiler]
* https://learn.microsoft.com/en-us/dotnet/api/system.runtime.compilerservices.callerfilepathattribute[CallerFilePathAttribute Class]
* https://learn.microsoft.com/en-us/dotnet/api/system.runtime.compilerservices.callerlinenumberattribute[CallerLineNumberAttribute Class]
* https://learn.microsoft.com/en-us/dotnet/api/system.runtime.compilerservices.callermembernameattribute[CallerMemberNameAttribute Class]
* https://learn.microsoft.com/en-us/dotnet/api/system.runtime.compilerservices.callerargumentexpressionattribute[CallerArgumentExpressionAttribute Class]
* https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/named-and-optional-arguments#optional-arguments[Named and Optional Arguments]

ifdef::env-github,rspecator-view[]

'''
== Implementation Specification
(visible only on this page)

=== Message

Move "xxx" to the end of the parameter list.


'''
== Comments And Links
(visible only on this page)

=== on 18 Nov 2015, 10:01:25 Tamas Vajk wrote:
\[~ann.campbell.2] I modified the sample code: there can't be any parameter without a default value after parameters with default values. (So I added the ``++null++`` default value to the ``++message++``)


And also modified the last sentence. It is possible to not specify all parameters in a call, but then you force the callers of this method to use named arguments. 

=== on 18 Nov 2015, 19:55:28 Ann Campbell wrote:
Okay, thanks [~tamas.vajk]

endif::env-github,rspecator-view[]
