【问题标题】:Overloading functions by return type in C# [duplicate]C#中按返回类型重载函数[重复]
【发布时间】:2014-09-06 20:45:08
【问题描述】:

我目前正在学习 C#,有人告诉我,你可以使用显式关键字实际重载方法返回类型,但他从未解释过如何。我到处google,也阅读了stackoverflow上的一些问题和答案,但我在任何地方都没有找到这样的东西,而且在大多数情况下,回答的人说不可能通过返回类型重载方法。毕竟,我开始认为没有这种可能性。现在有没有人可以通过使用显式关键字重载方法返回类型,甚至有可能吗? 先感谢您。

【问题讨论】:

标签: c# methods overloading explicit


【解决方案1】:

您不能按返回类型超载。但是,您可以定义多个仅根据返回类型不同的方法。这是两件不同的事情,经常被误解。

explicit 关键字仅与运算符有关。我认为这不是他的意思,你们中的一个人也可能会误用/误听实际的术语。

他可能指的是explicit interface implementation

这是唯一允许定义许多普通方法的方法(好吧,可能除了转换运算符,但它们是一些特殊的方法),这些方法仅在返回类型上有所不同。最常见的是GetEnumeratorIEnumerableIEnumerable<T> 都需要它:

public class Foo : IEnumerable<Bar>, IEnumerable
{
    public IEnumerator<Bar> GetEnumerator() { return null; }

    // IEnumerator GetEnumerator() { return null; } // IMPOSSIBLE

    IEnumerator IEnumerable.GetEnumerator() { return null; }
}

注意 Foo 类如何定义返回通用迭代器的 GetEnumerator。通常,现在不可能定义另一个满足经典 IEnumeratble 的 GetEnumerator。

但是,通过最后一行,通过显式接口实现,这是可能的。请注意方法名称是如何以接口名称为前缀的。

另外,请注意:所有显式实现都是私有的,这就是它没有访问说明符的原因。这意味着,尽管成功定义了它们,但您将无法超载。除非您将 Foo 转换为普通的 IEnumerable,否则显式将始终隐藏并且永远不会使用。

所以:

Foo foo = ...; // 
foo.GetEnumerator();   // calls normal typed GetEnumerator<>
((IEnumerable)foo).GetEnumerator();   // calls untyped GetEnumerator

警告词:该规则也包含在课程主体中,有时可能会非常误导:

public class Foo : IEnumerable<Bar>, IEnumerable
{
    public IEnumerator<Bar> GetEnumerator() { return null; }

    private void test()
    {
        // relatively obvious:

        this.GetEnumerator(); // calls GetEnumerator<>() !
        ((IEnumerable)this).GetEnumerator(); // calls plain GetEnumerator()
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        // very inobvious:

        return this.GetEnumerator(); // calls GetEnumerator<> ! no recursion!!

        // ((IEnumerable)this).GetEnumerator(); // would call itself recursively
    }
}

【讨论】:

  • 非常感谢,这很有帮助。我会投票,但我不能。稍后我会问这个人他是否真的重载运算符而不是方法,可能他用错了词或故意让我头疼。
  • 但是,您可以定义多个仅根据返回类型不同的方法 --- 真的吗?代码无法编译:static string F(int x) { return ""; } static int F(int y) { return 0; }
  • @LeiYang:你错过了我的很多帖子。您在评论中提供的代码是尝试创建因返回类型而异的重载。你看过我提供的代码示例吗? public class Foo 等等?仔细看看那个类里面有什么。甚至还有一个注释标记了你不能做的重载,并且有两个GetEnumerator方法定义,而且这些方法同名,相同的参数,不同的返回类型,这两个方法不是重载。
  • 嗨,我不是故意冒犯你,但我希望句子本身在没有其他上下文的情况下总是正确的,因为你有这么多分数。
  • @LeiYang:expecting the sentence itself to be always correct without other context - 好的,我知道如果不阅读整个答案可能会产生误导。我会考虑一下并尝试改进那里的措辞。 (虽然人类交流主要是关于上下文:)但我明白你的意思:))
【解决方案2】:

我不认为你可以重载返回类型。返回类型不包含在方法签名中。编译器在检查返回值是否会在更大的上下文中导致错误之前确定重载(这是如果您实际使用返回值)。

如果您不使用返回值会发生什么。编译器将不知道要使用什么重载。下面是一个这样的例子。

string func(int i){return "";}
int func(int i){return 0;}

void main(){
    func(1);//what happens here??? which method gets called??
} 

【讨论】:

    猜你喜欢
    • 2013-07-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-23
    相关资源
    最近更新 更多