== Why is this an issue?

The rules for method resolution can be complex and may not be fully understood by all developers.
The situation becomes even more challenging when dealing with method overloads that have optional parameter values.
 
This rule raises an issue when an overload with default parameter values is hidden by another overload that does not have the optional parameters.

=== What is the potential impact?

See the following example:

[source,csharp]
----
MyClass.Print(1);  // which overload of Print will be called?

public static class MyClass
{
  public static void Print(int number) { } 
  public static void Print(int number, string delimiter = "\n") { } // Noncompliant, default parameter value is hidden by overload
}
----

In this code snippet, the `Print` method is overloaded with two versions, where the first one hides the second one. 
This can lead to confusion and uncertainty about which overload of the method will be invoked when calling it.

== How to fix it

To address the problem you have a couple of options:

* Adjust the existing overloads to expose the optional parameters consistently across all overloads. By doing so, callers will have explicit control over which overload they want to invoke.
* Alternatively, you can differentiate the overloads by giving them distinct names. This approach clarifies the usage and intent of each overload, making it clear to developers which overload to use in different contexts.

=== Code examples

==== Noncompliant code example

[source,csharp,diff-id=1,diff-type=noncompliant]
----
MyClass.Print(1);  // which overload of Print will be called?

public static class MyClass
{
  public static void Print(int number) { } 
  public static void Print(int number, string delimiter = "\n") { } // Noncompliant: default parameter value is hidden by overload
}
----

==== Compliant solution

[source,csharp,diff-id=1,diff-type=compliant]
----
MyClass.PrintWithDelimiter(1);

public static class MyClass
{
  public static void Print(int number) { } 
  public static void PrintWithDelimiter(int number, string delimiter = "\n") { } // Compliant
}
----

== Resources

=== Documentation

* https://learn.microsoft.com/en-us/dotnet/standard/design-guidelines/member-overloading[Member overloading]
* https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/named-and-optional-arguments#optional-arguments[Optional arguments]

=== Articles & blog posts

* https://ericlippert.com/2011/05/09/optional-argument-corner-cases-part-one/[Optional argument corner cases - Eric Lippert's blog]

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

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

include::../message.adoc[]

include::../highlighting.adoc[]

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

include::../comments-and-links.adoc[]

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