c# - 带有可选参数的接口(interface)实现

标签 c# .net .net-4.5 c#-5.0

取这个界面:

interface ILogger
{
    void Store(string payload);
}

ILogger 的此类实现:

class Logger : ILogger
{
    void Store(string payload, bool swallowException = true)
    {
        ...
    }
}

我预计编译器会将 swallowException 识别为可选参数,从而满足接口(interface)的要求。相反,编译器会提示 Logger 没有实现接口(interface)成员 Store

我尝试的另一件有趣的事情是显式实现接口(interface),如下所示:

class Logger : ILogger
{
    void ILogger.Store(string payload, bool swallowException = true)
    {
        ...
    }
}

编译器发出警告“为参数‘swallowException’指定的默认值将无效,因为它适用于在不允许可选参数的上下文中使用的成员。”这似乎表明可选参数在某种程度上与显式接口(interface)定义不兼容,但为什么呢?

我可以通过使用两个单独的函数定义重载 Store 来解决这个问题(在可选参数存在之前的处理方式)。但是,我喜欢可选参数,因为它们的句法清晰,并且更希望它按照我期望的方式工作。

我知道可能有一个合理的(历史的或其他的)解释为什么会这样,但我似乎无法弄明白。

最佳答案

因为 C# 中的可选参数只是语法糖。

你的方法定义是

void Store(string payload, bool swallowException)

而不是

void Store(string payload)

这显然与界面不匹配。

默认参数的工作方式是编译器将默认值注入(inject)到方法的调用中。因此,如果您执行 Store(payload),编译器实际上会发出 Store(payload, true)。这对于理解默认参数非常重要——它是在调用者的编译时完成的。因此,如果您在不重新编译调用者的情况下更改被调用者中的默认参数,调用者仍将使用旧的默认参数。

这也解释了您收到的警告 - 因为默认值是由编译器显式传递的,并且您不能在不转换为接口(interface)的情况下调用接口(interface)的显式实现,您将没有机会永远使用默认值。

您实际上根本不想使用默认参数。简单地定义两个这样的方法:

void Store(string payload, bool swallowException)
{
  // Do your job
}

void Store(string payload)
{
  Store(payload, true);
}

这避免了上述两个问题 - 接口(interface)契约得到满足,默认参数现在是被调用者的一部分,而不是调用者。

就个人而言,我根本不在公共(public) API 方法中使用可选参数 - 当您决定在某个时候更改它们时,它们只是想引起麻烦。除非您可以确保它们将永远保持不变,否则不要使用它们。这同样适用于 constenum - 两者也是在编译时而不是运行时确定的。

请记住,包含默认参数的原因是允许您不传递一些参数。这对于 COM API 调用(否则会要求您将所有不想作为 Type.Missing 传递的参数)或 null 值的事情有意义.即使使用 false 也只是在自找麻烦,因为有人认为更好的默认值是 true - 突然间,一些调用者使用 true 而一些 false,尽管所有人都认为他们使用的是“默认值”。对于像你这样的情况,我会使用 bool? 代替,默认值为 null(或 default(bool?),以哪个为准你比较喜欢)。在方法代码本身中,您可以轻松地在适当的位置处理默认值 - 例如,通过执行 swallowException.GetValueOrDefault(true)

关于c# - 带有可选参数的接口(interface)实现,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30105563/

相关文章:

.net - 缺少异步重载?

c# 如何检查 QueryString Values 计数是否与键计数具有相同的值

c# - 为什么值变量不改变?

c# - MailKit - 如何获取每个附件的大小

c# - Entity Framework 是否具有 Linq2Sql 中 DataContext.GetTable<TEntity> 的等效项(ObjectContext.CreateQuery<T>?)

c# - 为什么获取 Http 请求和响应为时已晚

ajax - API Controller Post 方法返回类型/值

c# - 未分配属性的对象初始值设定项

c# - 随机生成敌人 XNA 4.0 (WP7)

c# - 使用 ReactiveUI 禁用和启用文本字段更改上的按钮