在重载时为什么不考虑函数的返回类型?

时间:2010-12-06 10:30:44

标签: c# .net c++ oop

  

可能重复:
  Function overloading by return type?

您好,

在重载时我们说参数列表必须按数字或类型不同,但在返回类型上无关紧要,为什么这样呢?

功能

//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不是?原因???

非常感谢任何帮助。

5 个答案:

答案 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看起来大致如下:Expression Tree

这个

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);