不同类型的重载函数和参数

本文关键字:参数 函数 重载 同类型 | 更新日期: 2023-09-27 17:51:10

"为什么VisualStudio不支持此代码"系列中的另一个问题…

给定一个重载函数

private string ConfigQuery(string username) {
    return "A";
}
private string ConfigQuery(int configId) {
    return "B";
}

以下代码是不可能的:

public Config ConfigAPI(int id=0) {
    string s = ConfigQuery(id==0?User.Identity.Name:id);
}

但是代码

public Config ConfigAPI(int id=0) {
    string s = (id==0?ConfigQuery(User.Identity.Name):ConfigQuery(id));
}

。这种行为合理吗?那么为什么我要使用一个重载的函数,而不是给他们更合适的名字,如UserNameConfigQuery, ConfigIdConfigQuery?

不同类型的重载函数和参数

一般来说,除了一些例外,比如使用反射,你是正确的,在重载方法中确实没有任何"功能",而不是用完全不同的名称创建一个新方法。这是因为,正如已经说过的,重载解析是在编译时完成的(同样,有一些罕见的例外,一般来说,应该避免),而不是在运行时完成的。

所以你真的没有获得任何东西,就功能而言,给每个方法一个不同的名字。这主要是为了方便程序员,并且为了让您的类型的用户清楚地知道该方法做同样的事情,它只是使用几个选项之一来完成它。

重载在编译时解决,而不是在运行时解决。三元运算符?:在运行时求值。所以在编译时,编译器不知道要链接到哪个函数重载,因为它不知道是否有id==0。这就是为什么第二个例子可以工作,因为在那里调用的重载可以在编译时解决。

重载的原因是为了方便调用具有不同数量或类型参数的同一逻辑函数。

是的,这是合理的行为。

请记住,要调用的重载是在编译时和运行时确定的。当然,id==0?在运行前不会被评估。

您可能仍然希望为:

使用重载
  • 不同类型的相同操作(例如myString.Replace('1', '5')myString.Replace("1", "5")),而不是使用泛型
  • 可选/默认参数(例如new Foo(bar) vs. new Foo(bar, baz)myRegex.Replace("blah", "yada") vs. myRegex.Replace("blah", "yada", 2)),而不是c#为可选和默认参数添加的正式支持,它们可能也有意义
同样,智能感知、代码文档和(正式的或导航的)搜索对的帮助也会大大减少对于不同命名的方法的帮助,这些方法实际上做(几乎)相同的事情,只是在参数的类型或数量上有所不同。例如,考虑查找和理解以下(接近)相同的:
  • QueryConfig(string username)QueryConfig(int configId)使用重载 UserNameConfigQuery(string username)ConfigIdConfigQuery(int configId)使用"更合适"的名称
  • Replace(string input, string replacement)Replace(string input, string replacement, int count)使用重载 CountRestrictedReplace(string input, string replacement, int count)UnrestrictedReplace(string input, string replacement)使用"更合适"的名称

您没有发布您得到的错误,但从外观上看,失败与重载无关。

该错误是由于三元操作符?不能获得string和int参数,它们需要具有相同类型或在它们之间进行隐式强制转换。

这篇文章解释得很好。

编辑:


从规范中,您可以了解失败的原因:

如果x是x类型,y是y类型,则:

  • 如果存在从X到Y的隐式转换(第6.1节),但不存在从Y到X的隐式转换,则Y是条件表达式的类型。

  • 如果存在从Y到X的隐式转换(第6.1节),但不存在从X到Y的隐式转换,则X是条件表达式的类型。

  • 否则,无法确定表达式类型,并发生编译时错误。