在C#中使用params的成本

有没有人建议在C#中使用params进行方法参数传递。 我正在考虑为前6个参数进行重载,然后使用paramsfunction进行7次重载。 我的理由是避免paramsfunction需要额外的数组分配。 这适用于一些高性能的实用方法。 任何建议? 创建所有重载是浪费代码吗?

老实说,每个人大喊“过早优化!”,我都有点困扰。 这就是原因。

  1. 你说的很有道理, 特别是你已经表明你正在开发一个高性能的库。
  2. 即使是BCL课程也遵循这种模式。 考虑string.FormatConsole.WriteLine所有重载。
  3. 很容易做对针对过早优化的运动背后的整个前提是,当您为了优化性能而做一些棘手的事情时,您可能会意外地破坏某些内容并使您的代码不易维护。 我不知道这有什么危险; 对于您自己以及可能处理您的代码的任何未来开发人员而言,您应该非常直截了当地做什么。

此外,即使您分析了两种方法的结果并且只看到了非常小的速度差异,仍然存在内存分配问题。 为每个方法调用创建一个新数组需要分配更多的内存,以后需要进行垃圾回收。 在某些需要“几乎”实时行为的情况下(例如算法交易, 我所在的领域),最小化垃圾收集与最大化执行速度同样重要。

所以,即使它给我带来了一些挫折:我说去吧。

(对于那些声称“编译器确实已经做过这样的事情”的人 – 我不会那么肯定。首先,如果是这样的话,我不明白为什么BCL课程会遵循这种模式,就像我一样已经提到了。但更重要的是,接受多个参数的方法与接受数组的方法之间存在非常大的语义差异。仅仅因为一个可以用作另一个的替代并不意味着编译器会或者应该 ,尝试这样的替代)。

是的,这是.NET框架使用的策略。 String.Concat()就是一个很好的例子。 它有多达4个字符串的重载,加上一个带有params字符串[]的后备字符串。 在这里非常重要,Concat需要快速,并且当他使用+运算符而不是StringBuilder时,它可以帮助用户陷入成功之中。

您将获得的代码重复是价格。 你可以对它们进行分析,看看加速是否值得维护头痛。

Fwiw:在.NET框架中有很多这样的微优化。 有些必要,因为设计师无法真正预测他们的课程将如何使用。 String.Concat()很可能在一个紧密的内部循环中使用,这对于程序性执行是至关重要的,例如,一个只在启动时运行一次的配置阅读器。 作为您自己代码的最终用户,您通常可以不必担心这一点。 反过来也是如此,当.NET框架代码不太可能被测量时,它显然没有微优化。 就像在核心代码很慢时提供重载一样。

您始终可以将Tuple作为参数传递,或者如果参数的类型始终相同,则为IList

正如其他答案和评论所说,你应该只在以下后进行优化:

  1. 确保正确的行为。
  2. 确定优化的必要性

我的观点是,如果你的方法能够获得无限数量的参数,那么它内部的逻辑就是以数组样式工作。 因此,对有限数量的参数进行重载将无济于事。 除非,您可以以更快的方式以完全不同的方式实现有限数量的参数。

例如,如果您将参数传递给Console.WriteLine,那里也会创建一个隐藏的数组,所以无论哪种方式最终都有一个数组。

而且,抱歉打扰丹涛,我也觉得这是不成熟的优化。 因为您需要知道在具有有限数量的参数的情况下进行重载会有什么不同。 如果您的应用程序对性能至关重要,则需要实现这两种方法并尝试运行测试并比较执行时间。

在这个阶段甚至不要考虑性能。 创建任何重载将使您的代码更容易编写,并在两年后的凌晨4点更容易理解。 有时这意味着params,有时这意味着避免它。

在你有一些有效的东西后,弄清楚这些是否是性能问题。 让参数变得更复杂并不难,但如果你现在增加不必要的复杂性,你永远不会让它们变得那么简单。

您可以尝试这样的方法来对性能进行基准测试,这样您就可以使用一些具体的数字来做出决策。

一般来说,对象分配比在C / C ++中稍快一些,对于小对象来说,删除要快得多,直到你每秒都有数万个这样做。 这是一篇关于内存分配性能的旧文章 。