您好,
在重载时我们说参数列表必须按数字或类型不同,但在返回类型上无关紧要,为什么这样呢?
功能
//Function 1
int Add(int a, int b)
{return a+b;}
//Function 2
Double Add(Double a, Double b)
{return a+b;}
//Function 3
Double Add(int a, int b)
{return (Double)a+b;}
函数1 2过载,而函数1和3不是?原因???
非常感谢任何帮助。
答案 0 :(得分:9)
编译器需要在编译时知道您要调用哪个函数。如果它们仅因返回类型而不同,则通常不可能。例如,考虑一下:
var result = Add(1, 2);
或
Console.WriteLine(Add(1, 2));
编译器无法知道您是否要执行函数1或3.即使您执行了
double x = Add(1, 2);
编译器不知道你是否想要调用函数3或(b)调用函数1并进行从int到double的隐式扩展转换。
答案 1 :(得分:4)
在许多情况下,这种重载不起作用。这是其中两个:
您不关心方法的结果,并将其称为:
Add(3, 4);
这应该调用方法1还是3?
您使用var
分配结果
var result = Add(3, 4);
这种超载最多是模棱两可的,因此不允许这样做。
答案 2 :(得分:3)
其他答案涉及为什么,但另外一点:在C#中你可以通过使用(滥用?)隐式转换运算符来模拟基于返回类型的重载(并推迟)操作):
using System;
class Program {
static void Main() {
int i = Add(3, 5); // prints: int overload called
double d = Add(3, 5); // prints: double overload called
}
static SuperMagicAdder Add(int a, int b)
{ return new SuperMagicAdder(a, b); }
}
struct SuperMagicAdder {
private readonly int a,b;
public SuperMagicAdder(int a, int b) { this.a = a; this.b = b; }
public override string ToString() { return a + "+" + b; }
public static implicit operator int (SuperMagicAdder value) {
Console.WriteLine("int overload called");
return value.a + value.b;
}
public static implicit operator double (SuperMagicAdder value) {
Console.WriteLine("double overload called");
return (double)value.a + value.b;
}
}
答案 3 :(得分:1)
请注意,有趣的是,C#中的匿名函数文字在结果类型上重载,似乎没有任何问题。
在C#中,lambda可以是两个截然不同的东西:
Delegate
的子类)lambda文字的结果类型区分纯:
Func<int, int> l = (i) => i + i * i;
是一段可执行代码。我可以说
Console.WriteLine(l(3));
我将获得12
。
Expression<Func<int, int>> e = (i) => i + i * i;
是该操作的抽象表示。我可以说
Console.WriteLine(e);
我会得到
i => (i + (i * i))
请注意,不仅仅是原始文本。它真的是抽象表示的渲染。表达式及其内部的额外括号是存在的,因为ToString()
执行了AST的实际树遍历并对其进行了渲染。 AST看起来大致如下:
这个
var v = (i) => i + i * i;
完全是非法的,因为 lambda在结果类型上重载,但var
关键字显示“使用结果类型来计算v
的类型”。
答案 4 :(得分:0)
允许返回类型成为签名的一部分会在重载决策中产生很大的歧义。
例如,考虑:
Add(2,3);
我们“丢弃”方法返回的值,但应该调用哪个重载?
它不适用于隐式类型,或者将值赋给与return-type兼容的变量。 E.g:
var sum = Add(2,3);
object sum = Add(2,3);