== Why is this an issue?

https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/named-and-optional-arguments#optional-arguments[Default arguments] are determined by the static type of the object. 

[source,csharp]
----
class Base
{
    public virtual void Run(int distance = 42) { /* ... */ }
}

class Derived : Base
{
    public override void Run(int distance = 5) { /* ... */ }
}

Base x = new Base();
x.Run(); // Here the default value of distance is 42
Derived d = new Derived();
d.Run(); // Here the default value of distance is 5
Base b = new Derived();
b.Run(); // Here the default value of distance is 42, not 5
----

If a default argument is different for a parameter in an overriding method, the value used in the call will be different when calls are made via the base or derived object, which may be contrary to developer expectations.

Default parameter values in https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/interfaces/explicit-interface-implementation[explicit interface implementations] will be never used, because the static type of the object will always be the implemented interface. Thus, specifying default values in this case is confusing.

[source,csharp]
----
interface IRunner
{
    void Run(int distance = 42) { /* ... */ }
}

class Runner : IRunner
{
    void IRunner.Run(int distance = 5) { /* ... */ }
}

IRunner x = new Runner();
x.Run(); // Here the default value of distance is 42
Runner d = new Runner();
d.Run(); // This will not compile as the Run method is only visible through the specified interface
----

=== Noncompliant code example

[source,csharp,diff-id=1,diff-type=noncompliant]
----
using System;

public class Base
{
    public virtual void Write(int i = 42)
    {
        Console.WriteLine(i);
    }
}

public class Derived : Base
{
    public override void Write(int i = 5) // Noncompliant
    {
        Console.WriteLine(i);
    }
}

public class Program
{
    public static void Main()
    {
        var derived = new Derived();
        derived.Write(); // writes 5
        Print(derived); // writes 42; was that expected?
    }

    private static void Print(Base item)
    {
        item.Write();
    }
}
----

=== Compliant solution

[source,csharp,diff-id=1,diff-type=compliant]
----
using System;

public class Base
{
    public virtual void Write(int i = 42)
    {
        Console.WriteLine(i);
    }
}

public class Derived : Base
{
    public override void Write(int i = 42)
    {
        Console.WriteLine(i);
    }
}

public class Program
{
    public static void Main()
    {
        var derived = new Derived();
        derived.Write(); // writes 42
        Print(derived);  // writes 42
    }

    private static void Print(Base item)
    {
        item.Write();
    }
}
----

== Resources

=== Documentation

* https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/named-and-optional-arguments#optional-arguments[Optional arguments]
* https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/interfaces/explicit-interface-implementation[Explicit Interface Implementation]

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

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

=== Message

* Use the default parameter value defined in the overridden method.
* Remove the default parameter value to match the signature of overridden method.
* Add the default parameter value defined in the overridden method.
* Remove the default parameter value from this explicit interface implementation.


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

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

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