【问题标题】:Two methods with the same signature except for optional parameter两个具有相同签名的方法,除了可选参数
【发布时间】:2015-11-27 16:54:45
【问题描述】:

我一直在研究我的项目,无意中编写了两个具有相同签名的方法,除了可选参数。令我惊讶的是,代码编译正常。

public async Task<List<CategoryApiModel>> GetCategoriesAsync( int contentLanguageId = 0 )
{
    ...
}

public async Task<List<CategoryApiModel>> GetCategoriesAsync( string languageTag = "" )
{
    ...
}

我知道,当使用空参数调用时,这会导致调用不明确,但我很惊讶这甚至被允许作为声明本身。谁能解释一下,为什么会这样?

【问题讨论】:

标签: c# overloading optional-parameters


【解决方案1】:

实际上,您的程序可以正常编译直到您至少有一个 GetCategoriesAsync() 调用。然后你会得到“错误 CS0121: The call is ambiguous”。

【讨论】:

  • 是的,这正是我注意到的。令我惊讶的是,当这个调用不存在时,代码会编译。
  • 没有模棱两可的调用,代码是有效的。在你的情况下它可能看起来很奇怪,但当你有多个参数时它是有意义的。
【解决方案2】:

代码肯定能正常编译,因为你在第二个方法中把入参的类型改成了String,这也进入了方法的签名中。这将执行方法重载。 希望这能回答你的问题。

【讨论】:

  • 但这有意义吗?我的意思是你不能调用没有参数的方法,对吧?那么会选择哪一个呢?
  • @lorenzalbert 不,这没有意义,编译器会因模棱两可的调用而出错,但是如果填写了“可选”参数,这两种方法仍然可以使用,因此仍应合法允许参数传递时调用。
  • @lorenzalbert 如果您尝试在不提供任何参数的情况下调用方法,那么通常它会给您编译错误,即没有声明此类方法。在上面的代码中,没有没有参数的方法。希望这能消除您的困惑。 :)
【解决方案3】:

存在问题,会出现编译错误,但仅当某些代码实际尝试使用其中一种参数不明确的方法时。

如果您说两个文件,每个文件定义这两个函数之一,这可能很有用(如果可能是草率和混乱)。如果只有一个在范围内,则可以使用默认参数,并且不会对编译器产生歧义。但是,这当然可以被认为是草率,因为它可能会导致一个可能不会被注意到的错误。

【讨论】:

  • 这不是编译器错误,直到运行时才会发生。
  • @Frisbee 所以你是说你没有得到 Compiler Error CS0121 msdn.microsoft.com/en-us/library/ky5f1hz8%28v=vs.90%29.aspx
  • 如果方法在没有参数的情况下调用,这将在编译期间发生
  • 我假设 OP 在程序中有一个没有参数的调用。
【解决方案4】:

代码可以正常编译,因为overloads 可以通过将正确的参数传递给它们来分别调用。

GetCategoriesAsync(1);

因此,出于显而易见的原因,代码可以正常工作。

但是,如果有一个调用,像这样:GetCategoriesAsync(),它现在会抛出一个编译错误:

错误 CS0121:调用不明确

错误消息中明确说明的原因是,该方法没有最佳匹配,因为它可以轻松适应两者。

值得注意的是,如果函数有一个空重载,即

public async Task<List<CategoryApiModel>> GetCategoriesAsync()
{}

代码将编译,因为它将使用该调用。因此,可以通过执行以下操作来转移问题:

public async Task<List<CategoryApiModel>> GetCategoriesAsync()
{
     return GetCategoriesAsync(0);
}

虽然我不会推荐它。

【讨论】:

  • 为什么编译器更喜欢无参数方法而不是带有可选参数的方法?我觉得这很混乱,我认为应该抛出异常。
  • P.S.我在csharpindepth.com/Articles/Overloading 上方看到了一个很棒的链接,但它并没有说明为什么选择了这种方法。
【解决方案5】:

当然,您可以通过传递正确类型的默认值来对这两种方法使用“无参数”的行为。

例如: GetCategoriesAsync(0) 用于第一个方法调用。 GetCategoriesAsync("") 用于第二个方法调用。 因此,行为将与您不传递参数相同,因为您传递的是默认值(请注意,默认值不是类型的默认值,而是在方法中手动设置的默认值,如果未提供参数)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-11-12
    • 2018-11-04
    • 1970-01-01
    • 2020-03-20
    • 2020-10-23
    • 1970-01-01
    相关资源
    最近更新 更多