有没有人建议在 C# 中使用参数传递方法参数。我正在考虑对前 6 个参数进行重载,然后使用 params 功能对第 7 个参数进行重载。我的理由是避免 params 功能所需的额外数组分配。这适用于一些高性能的实用方法。有什么建议吗?创建所有重载是否浪费代码?
6 回答
老实说,大家都在喊“过早的优化”,我有点烦。这就是为什么。
- 你说的很有道理,特别是当你已经表明你正在开发一个高性能库时。
- 甚至 BCL 类也遵循这种模式。考虑
string.Format
or的所有重载Console.WriteLine
。 - 这很容易搞定。反对过早优化运动背后的整个前提是,当您为了优化性能而做一些棘手的事情时,您很可能会意外破坏某些东西并降低您的代码可维护性。我看不出这里有什么危险。对于您自己以及任何可能处理您的代码的未来开发人员来说,您正在做的事情应该非常简单。
此外,即使您分析了这两种方法的结果并且只看到了非常小的速度差异,仍然存在内存分配问题。为每个方法调用创建一个新数组需要分配更多内存,以后需要进行垃圾回收。在某些需要“近乎”实时行为的场景中(例如算法交易,我所在的领域),最小化垃圾收集与最大化执行速度同样重要。
所以,即使它为我赢得了一些反对票:我说去吧。
(对于那些声称“编译器肯定已经做了这样的事情”的人——我不太确定。首先,如果是这样的话,我不明白为什么 BCL 类会遵循这种模式,因为我已经已经提到了。但更重要的是,接受多个参数的方法和接受数组的方法之间存在很大的语义差异。仅仅因为一个可以用作另一个的替代品并不意味着编译器会或应该,尝试这样的替换)。
是的,这就是 .NET 框架使用的策略。String.Concat() 就是一个很好的例子。它具有最多 4 个字符串的重载,以及一个带有参数 string[] 的后备字符串。在这里非常重要,Concat 需要快速,并且当用户使用 + 运算符而不是 StringBuilder 时,它可以帮助用户陷入成功的陷阱。
您将获得的代码重复就是价格。您将对其进行分析,以查看加速是否值得维护头痛。
Fwiw:.NET 框架中有很多这样的微优化。有点必要,因为设计师无法真正预测他们的类将如何被使用。String.Concat() 很可能用在对程序性能至关重要的紧密内部循环中,例如,只在启动时运行一次的配置读取器。作为您自己代码的最终用户,您通常可以不必担心这一点。反之亦然,.NET 框架代码明显没有微优化,而它们的好处不太可能是可衡量的。就像在核心代码很慢时提供重载一样。
我的观点是,如果您的方法能够获取无限数量的参数,那么它内部的逻辑以数组样式运行。因此,对有限数量的参数进行重载将无济于事。除非,您可以以更快的方式以完全不同的方式实现有限数量的参数。
例如,如果您将参数传递给 Console.WriteLine,那么其中也会创建一个隐藏的数组,因此无论哪种方式,您最终都会拥有一个数组。
还有,不好意思打扰了丹涛,我也觉得是过早的优化。因为您需要知道使用有限数量的参数进行重载会有什么不同。如果您的应用程序对性能非常关键,那么您需要实现这两种方式并尝试运行测试并比较执行时间。
甚至不要考虑现阶段的表现。在两年后的凌晨 4 点,创建任何能让你的代码更容易编写和更容易理解的重载。有时这意味着参数,有时这意味着避免它。
在你得到一些有用的东西之后,找出这些是否是性能问题。让参数变得更复杂并不难,但如果你现在增加不必要的复杂性,以后你永远不会让它们变得更简单。
您可以尝试这样的方法来对性能进行基准测试,这样您就有一些具体的数字可以用来做决定。
一般来说,对象分配比 C/C++ 中的稍快,而小对象的删除速度要快得多——直到每秒生成数万个对象。这是一篇关于内存分配性能的旧文章。