【问题标题】:Why aren't C#'s Math.Min/Max variadic?为什么 C# 的 Math.Min/Max 不是可变参数?
【发布时间】:2012-03-15 02:58:42
【问题描述】:

我需要找到 3 个值之间的最小值,我最终做了这样的事情:

Math.Min(Math.Min(val1, val2), val3)

这对我来说似乎有点傻,因为其他语言为此使用可变参数函数。我非常怀疑这是一个疏忽。

为什么一个简单的 Min/Max 函数不应该是可变参数的?有性能影响吗?有没有我没注意到的可变参数版本?

【问题讨论】:

  • 不是你要找的,但 LINQ 有一个 IEnumerable 的最小扩展
  • 调用可变参数函数分配一个数组。对于简单的最小值/最大值而言,这可能被认为开销太大。

标签: c# variadic-functions


【解决方案1】:

如果它是一个集合(IEnumerable<T> 的子类),则可以轻松使用 System.Linq 库中的函数

int min = new int[] {2,3,4,8}.Min();

此外,您自己也很容易实现这些方法:

public static class Maths {

    public static T Min<T> (params T[] vals) {
        return vals.Min();
    }
    public static T Max<T> (params T[] vals) {
        return vals.Max();
    }

}

您可以只使用简单的标量调用这些方法,因此Maths.Min(14,25,13,2) 将给出2

这些是泛型方法,因此无需为每种类型的数字(int,float,...)实现此方法

我认为这些方法一般没有实现的基本原因是,每次调用此方法时,都应该创建一个数组(或至少一个IList 对象)。通过保留低级方法,可以避免开销。但是,我同意可以将这些方法添加到 Math 类中,以使一些程序员的生活更轻松。

【讨论】:

  • 我认为现在确实如此,而且大多数人都想要一个务实的解决方案。还有其他有关理论计算机科学和编程语言范式的 stackexchange 站点。
  • @CommuSoft:如果他问怎么做,那么你原来的答案会起作用,但他问为什么。虽然应该问的问题是有争议的,但通常允许关于特定 API 的抽象问题,因为显然这个问题不是关于计算机科学的一般问题(尽管可以将其更改为一个......)
  • 我说答案可能是使用数组或集合会降低方法的性能。如果我是正确的,这些方法甚至都不存在。它们是低级代码的别名(例如 80x86 架构中的 MINPS)。我还提供了一种解决这个问题的方法,而不必为每种类型的数字表示编写 2 个方法,因为大多数会找到这个主题的人只是在寻找解决方案。
  • 我想这是一个不错的答案。我更多地研究了为什么 C# 没有实现它,但我想这是使用 Linq 解决的。感谢您的信息!
  • @DJQuimby:与其抱怨这个答案,不如自己写一个你更喜欢的答案?
【解决方案2】:

CommuSoft 已经解决了如何在 C# 中实现等价,所以我不会重读那部分。

为了具体解决您的问题“为什么 C# 的 Math.Min/Max 不是可变参数?”,我想到了两个想法。

首先,Math.Min(和 Math.Max)实际上不是 C# 语言功能,它是 .NET 框架库功能。这可能看起来很迂腐,但这是一个重要的区别。事实上,C# 没有提供任何特殊用途的语言特性来确定两个(或多个)潜在值之间的最小值或最大值。

其次,正如 Eric Lippert 多次指出的那样,语言特性(可能还有框架特性)不会被“移除”或主动排除 - 在有人设计、实现、测试、记录并发布该特性之前,所有特性都未实现. See here for an example.

不是 .NET 框架开发人员,我无法谈论发生的实际决策过程,但似乎这是一个根本没有上升到包含级别的功能的经典案例,类似于序列 foreach “功能”Eric 在提供的链接中讨论。

【讨论】:

  • 是的,这有点迂腐,但这就是我对 SO 的期望。我知道内置语言和库功能之间的区别(我的意思是,您将其命名为 Math)。我应该说 .NET 和 Mono(两个主要的实现,具有几乎相同的标准库)。不错的链接,顺便说一句。
  • @tjameson 在这种情况下,您可能想要更改问题的标题和标签,因为正如您所说,这实际上不是 C# 问题。谢谢。
  • 如果它真的困扰着您,请继续编辑它。我想不出一种在不使标题超长的情况下包含 .NET 和 Mono 的方法。我认为这很好。我不知道标准库中没有等效函数的 C# 实现。
【解决方案3】:

我认为 CommuSoft 提供了一个可靠的答案,至少适合人们在这些方面进行搜索,并且应该被接受。

话虽如此,原因肯定是为了避免不太可能人们想要比较一个组而不是两个值的用例所需的开销。

正如@arx 所指出的,对于最常用的情况,使用参数将是不必要的开销,但对于必须在内部使用以通过数组的循环而言,这也是很多不必要的开销n - 1 次。

我可以很容易地看到一个论点,即创建方法 除了基本形式,但使用 LINQ 就不再需要了。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-04-28
    • 1970-01-01
    • 1970-01-01
    • 2022-07-14
    • 1970-01-01
    • 2010-11-23
    • 1970-01-01
    • 2019-10-05
    相关资源
    最近更新 更多