【问题标题】:Function overloads in C# are they a good idea? [closed]C# 中的函数重载是个好主意吗? [关闭]
【发布时间】:2016-04-09 21:51:10
【问题描述】:

所以我有一种情况,根据我想要的最终结果,我需要不同数量的函数参数。

我是 C# 新手,听说过重载函数,这是我以前没有见过的(我从 JavaScript 开始)。

但它看起来有点脏,即使它确实有效,也不是一个好习惯。使用重载函数通常不是一个好主意吗?我可能会做更多的工作,但重载确实让生活更轻松。

使用多个同名方法感觉很不舒服。这些被认为是标准功能和可接受的代码实践吗?或者它会在未来导致一些我没有经验的人还不知道的混乱问题,因此我应该避免它?

【问题讨论】:

  • 您可以将任意数量的参数传递给 javascript 中的方法。没有冒犯,我个人认为超载比这样做更省钱
  • 方法有很多参数不是一个好习惯,方法最多可以有3个参数,如果你需要更多,建议你创建一个类。但是重载方法是一种很好的做法,因此您将有一个方法可以执行您想要的操作,而其他方法只需将默认值设置为参数。
  • @Henrique 最多 3 个?我以前从未听说过这条规则。
  • @WDUK - 我认为 Henrique 的意思是“最多 3 个参数”作为指导,与硬限制无关。
  • 谢谢,我想大多数人看到标题并报告它。我仍然习惯于用正确的方式来表达问题 - 对网站来说仍然是新事物。

标签: c#


【解决方案1】:

函数重载。

命名实际上是方法重载。 C# 与返回值和不返回值的 方法 没有直接区别。因此方法

但是看起来有点脏

这是该语言的一个关键组成部分,这是一种常见的做法,绝对不会令人不悦。

即使它确实有效,也不是一个好习惯。

我们的想法是为消费者提供不同的变体。一位消费者可能只使用 X 型,而仅提供 Y 型。通过提供更多,库和/或实例更加灵活。此外,它通过让消费者转换数据以将其放入方法中来吸取失败点。

(我从 JavaScript 开始)。

不要尝试以人们习惯的语言的风格进行编程。按照设计使用任何新语言的特定功能。试图在 C# 中编写 Java 或在 C# 中编写 Ruby 是愚蠢的。所有语言都有其设计要点...针对语言编程,而不是针对编程风格。

只是感觉很不舒服,有多个同名的方法。

来自一种不是类型安全的语言,这是可以理解的反应。但请记住,编译器正在强制执行 safety,因此小部件 X 仅与小部件 X 匹配;这是一个真正的功能,而不是噱头。

坦率地说,当我看到不提供多个重载的代码时,我认为它要么是开发人员的懒惰,要么是某种可怕的时间紧缩,因此代码匆忙。

不要过火...只需提供足够的重载以使该类可供大多数消费者使用。

或者以后会不会导致一些乱七八糟的问题

如果一个不一致,可能是。

所以在变量的位置上要保持一致。如果int 启动该方法,则另一个方法也应该以相同的int 开头;如果提供。不要混淆顺序。

【讨论】:

  • “这个想法是为消费者提供不同的变体。一个消费者可能只使用 X 类型,而只提供 Y 类型。”完全正确 - 特别是如果 XY 不相互继承或没有可以使用的通用接口/基类。 “不要试图以人们习惯的语言风格进行编程......” 没错。这个答案中的一切都很好! +1
【解决方案2】:

考虑以下类:

public class MyClass 
{
    public void MyMethod(int a, object b)
    {
    }
}

如果其他人这样称呼你的班级:

new MyClass().MyMethod(1, 1);

然后在您的程序集的未来版本中添加一个无辜的重载:

public class MyClass 
{
    public void MyMethod(int a, object b)
    {
    }

    public void MyMethod(object a, int b)
    {
    }
}

其他人的代码不会针对新程序集进行编译。

你说得对,方法重载会带来问题……但它并不总是有问题。

假设一个简单的例子——你有一个方法在Type - T 上运行。如果您想添加一个方法重载来处理第二个Type U,请考虑TU 可能有哪些接口和基类(包括TU 相互扩展) .如果有一个常见的Type,请考虑在设计时将其设为参数类型(如果足够具体的话)。如果没有,那么您可能需要方法重载。一个很好的人为示例可能是返回数字平方的方法。对于具有* 运算符的Type 没有通用抽象(您可以在C# 中编写自己的)。因此,您必须使用 (2) 个方法来处理 intdouble

public int SquareMe(int x) { return x * x; }
public double SquareMe(double x) { return x * x; }

但是,如果您发现自己想要创建一个在 List<T>IEnumerable<T>T[] 上运行的方法,您最好编写该方法来接受 IEnumerable<T>(并且只需调用 @987654342 @ 立即在其上,以防止 IEnumerable 在您的代码多次需要它时多次扩展 - 如果您只是 foreach'ing 它一次,则无需扩展它)这样您就只剩下(1) 编写测试的方法。每种方法,特别是在公开使用的 API 上,都需要维护、记录、测试、自动化等。通常越简单越好(但复杂性也有它的位置)。很难给出一个设计 API 的算法(如果有这样的算法,我们可以将设计生成为某个假设程序的输出,是吗?)

在设计供公共使用的类和接口时,您应该非常小心方法重载(以及您的整个 API,一般来说 - 方法重载引入细微的破坏性更改只是需要考虑的一件事 - 几乎任何更改都可能是一个突破性的变化)。如果您的 API 被所有人(例如 Microsoft)使用,那么对 API 的所有更改都必须经过深思熟虑,并且至少有 0 个重大更改。

如果它是用于“内部”使用(并且您可以在构建时检测编译中断),那么如果编译器满意,方法重载本身就不应该是太大的交易。话虽如此 - 由于 C# 将选择什么,有人可能会意外调用不同的重载。使用直观(即主观上)与方法所做内容相匹配的显式方法名称(微软通常建议用 C# 拼写出来)可能比重载问题更重要。

与其他事物一样,这种语言特性是在显式和隐式之间进行权衡,以及它是否是一个好主意因情况而异;方法重载既可以使用也可以滥用。一般来说,在发展自己的风格之前,尝试学习一门新语言的现有实践、模式和文化,这样你就可以利用之前每个人的成功和失败。方法重载肯定在 C# 中占有一席之地。

【讨论】:

  • 基本上这归结为要提防参数之一是对象的重载。
  • 我很高兴我读到了这个答案,因为我碰巧有一个参数是一个对象!
  • 叹息。它是 funcname(IDictionary, IEnumerable>) 和 funcname(IEnumerable>, IDictionary)。如果您传递 2 个 IDictionary 对象,则会产生歧义。
  • 提及object 情况是一个极好的信息块。就是这样...... .Net 1. :-) +1
  • @WordsLikeJared 好多了。请注意“ToArray()”建议是不好的。使用 IEnumerable 的方法不应调用 ToArray,除非它必须这样做。
【解决方案3】:

所以,您所使用的语言的核心功能可以使您的情况变得更容易......您对此感到担忧吗?我不会太担心的。

尝试一下可能是个好主意,一旦你对它感到满意,就把它带到 codereview.stackexchange.com 以获得一些反馈。

【讨论】:

  • 所以它是 C# 的设计特性,不像人们根据代码如何解释方法调用而利用的一些技巧。这是我不确定的。
  • @WDUK 这当然是一个设计考虑因素。我最近回答了一个关于非常具体情况的问题,设计文档表明即使是这样也经过仔细考虑和指定:stackoverflow.com/questions/36407947/…
【解决方案4】:

如果改变签名的原因是因为“您想要的最终结果”不同,那么这就是具有不同功能的情况。

当您有许多可选参数时,重载很有帮助。如果您有五个可选参数,那么如果您指定一些而不指定其他参数,将会发生什么就不那么明显了。如果您创建重载,那么您可以为函数的不同版本提供所需的参数。也许在幕后,他们都可以调用带有可选参数的私有方法,但这仍然对公共使用隐藏。

【讨论】:

    【解决方案5】:

    为什么不直接使用可选参数?

    void Foo (int op = 42)
    {
    
    if (x!=42)
     //do something
    else
    
    }
    int x = 33;
    Foo();
    Foo(x);
    

    【讨论】:

      猜你喜欢
      • 2018-08-17
      • 2012-04-19
      • 2010-11-27
      • 2019-08-24
      • 1970-01-01
      • 2010-10-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多