C# 为什么实现中允许的默认值与接口上定义的默认值不同?

C# 为什么实现中允许的默认值与接口上定义的默认值不同?,c#,interface,optional-parameters,C#,Interface,Optional Parameters,我最近遇到了以下行为: internal interface IOptionalParamTest { void PrintMessage(string message = "Hello"); } class OptionalParamTest : IOptionalParamTest { public void PrintMessage(string message = "Goodbye") { Console.WriteLine(message);

我最近遇到了以下行为:

internal interface IOptionalParamTest
{
    void PrintMessage(string message = "Hello");
}

class OptionalParamTest : IOptionalParamTest
{
    public void PrintMessage(string message = "Goodbye")
    {
        Console.WriteLine(message);
    }
}

internal class Program
{
    static void Main()
    {
        IOptionalParamTest usingInterface = new OptionalParamTest();
        usingInterface.PrintMessage(); // prints "Hello"

        OptionalParamTest usingConcrete = new OptionalParamTest();
        usingConcrete.PrintMessage();// prints "Goodbye"
    }
}
我的问题是,;为什么编译器不使用与接口上定义的不同的默认值拒绝PrintMessage的实现?

调用PrintMessage();只是语法上的糖。没有接受零参数的方法PrintMessage()。编译器只需插入正确的值。因此,编译器将第一次调用更改为:

PrintMessage("Hello");
因为usingInterface的编译时类型是IOPTationalParamTest

usingConcrete的编译时类型是OptionalParamTest,因此它在那里查找要插入的值,调用变为

PrintMessage("Goodbye")
调用PrintMessage();只是语法上的糖。没有接受零参数的方法PrintMessage()。编译器只需插入正确的值。因此,编译器将第一次调用更改为:

PrintMessage("Hello");
因为usingInterface的编译时类型是IOPTationalParamTest

usingConcrete的编译时类型是OptionalParamTest,因此它在那里查找要插入的值,调用变为

PrintMessage("Goodbye")
接口实现不使用默认值(而是:只有调用站点使用默认值);它在常规方法声明中是允许的,因此您仍然可以使用默认参数值特性,但不要求它是相同的值。如果我们添加一个显式接口实现,它会变得更有趣:

void IOptionalParamTest.PrintMessage(string message = "what happens here?")
{
    Console.WriteLine(message);
}
在回答问题“这里发生了什么?”:编译器警告:

为参数“message”指定的默认值将无效,因为它适用于在不允许可选参数的上下文中使用的成员

接口实现不使用默认值(而是:只有调用站点使用默认值);它在常规方法声明中是允许的,因此您仍然可以使用默认参数值特性,但不要求它是相同的值。如果我们添加一个显式接口实现,它会变得更有趣:

void IOptionalParamTest.PrintMessage(string message = "what happens here?")
{
    Console.WriteLine(message);
}
在回答问题“这里发生了什么?”:编译器警告:

为参数“message”指定的默认值将无效,因为它适用于在不允许可选参数的上下文中使用的成员


为什么它需要拒绝它?我想我认为可选参数是方法签名的一部分,但看看已经发布的相关问题,似乎不是这样。为什么它需要拒绝它?我想我认为可选参数是方法签名的一部分,但是看看已经发布的相关问题,情况似乎并非如此。嗯,有趣的警告信息。在我的特定场景中,我决定让这个论点成为非可选的,以消除对预期会发生什么的不清晰。嗯,有趣的警告消息。在我的特定场景中,我决定让这个论点成为非选择性的,以消除对预期会发生什么缺乏明确性的问题。