为什么Java,C#和C ++没有范围?

时间:2009-01-29 10:53:13

标签: c# java c++ typing spec#

AdaPascal和许多其他语言支持范围,一种子类型整数的方法。 范围是有符号整数值,其范围从值(第一个)到另一个(最后一个)。 在OOP中实现相同的类很容易,但我认为本机支持该功能可以让编译器进行额外的静态检查。

我知道静态验证一个范围内定义的变量不会“溢出”运行时,即由于输入错误,我不可能做到,但我认为可以做些什么。 我想到了Design by Contract方法(Eiffel)和Spec#(C# Contracts),它们提供了更为通用的解决方案。

是否有一个更简单的解决方案,至少在编译时检查C ++,C#和Java中的静态越界分配?某种static-assert

编辑:我了解“范围”可用于不同目的:

  1. 迭代
  2. 枚举
  3. 整数子类型
  4. 我会专注于后者,因为前者很容易在C *语言上映射。 我想到了一组封闭的值,比如音乐音量,即从1到100的范围。我想用一个值递增或递减它。我希望在静态溢出的情况下出现编译错误,例如:

    volume=rangeInt(0,100);
    volume=101;  // compile error!
    volume=getIntFromInput(); // possible runtime exception
    

    感谢。

11 个答案:

答案 0 :(得分:4)

在实践中,子范围类型实际上并不是非常有用。我们通常不会分配固定长度的数组,也没有理由使用固定大小的整数。通常我们看到固定大小的数组,它们作为枚举,我们有一个更好的(虽然“更重”)解决方案。

子范围类型也使类型系统复杂化。在变量之间引入约束比固定常数更有用。

(强制性地提到整数应该是任意合理语言的任意大小。)

答案 1 :(得分:3)

自1.4版以来,Java有一个断言关键字。如果您按合同进行编程,则可以自由地使用这些来检查正确的分配。并且应该在设置之前检查对象内应该落在特定范围内的任何可变属性。您还可以抛出IllegalArgumentException。

为什么没有范围类型?我的猜测是,原始设计师没有在C ++中看到它,并且认为它不像其他功能那样重要。

答案 2 :(得分:3)

当您可以简洁地执行超出该范围的操作时,范围最有用。这意味着关闭。至少对于Java和C ++,与迭代器相比,范围类型会很烦人,因为您需要定义一个内部类来定义您将在该范围内执行的操作。

答案 3 :(得分:2)

Pascal(以及Delphi)使用子范围类型,但它仅限于序数类型(整数,字符和偶数布尔值)。

它是一个带有额外类型检查的整数。您可以使用课程以其他语言伪造它。这样做的好处是可以应用更复杂的范围。

答案 4 :(得分:2)

对于C ++,目前正在实施受约束值变量的lib,并将在boost库中提出:http://student.agh.edu.pl/~kawulak/constrained_value/index.html

答案 5 :(得分:1)

在C#中你可以这样做:

foreach(int i in System.Linq.Enumerable.Range(0, 10))
{
    // Do something
}

答案 6 :(得分:1)

C ++允许您通过模板实现这些类型,我认为已经有一些可用的库。但是,我认为在大多数情况下,其好处太小,不足以证明增加的复杂性和编译速度的损失。

至于静态断言,它已经存在。 Boost有BOOST_STATIC_ASSERT,在Windows上,我认为微软的ATL库定义了类似的。

boost::type_traits和boost :: mpl可能是你实现这类事情的最好朋友。

答案 7 :(得分:1)

滚动自己的灵活性比将其内置到语言中更好。例如,如果您想要饱和算术,而不是为超出范围的值抛出异常,该怎么办?即。

MyRange<0,100> volume = 99;
volume += 10; // results in volume==100

答案 8 :(得分:1)

我想补充Tom Hawtin的回应(我同意),对于C ++,范围的存在并不意味着它们会被检查 - 如果你想要与一般的语言行为保持一致 - 作为数组访问,对于例如,无论如何也不进行范围检查。 对于C#和Java,我认为决定是基于性能 - 检查范围会增加负担并使编译器复杂化。

请注意,范围在调试阶段主要是有用的 - 在生产代码中(理论上)不应发生范围违规。因此,范围检查最好不是在语言本身内部实现,而是在前后条件下实现,在生成发布版本时可以(应该)将其删除。

答案 9 :(得分:1)

这是一个老问题,但只是想更新它。 Java本身没有范围,但是如果你真的想要这个功能,你可以使用 Commons Lang ,它有很多范围类,包括 IntRange

IntRange ir = new IntRange(1, 10);

奇怪的是,这在Commons Math中并不存在。我部分同意接受的答案,但我不认为范围是无用的,特别是在测试用例中。

答案 10 :(得分:0)

JSR-305为范围提供了一些支持,但我不知道它何时会成为Java的一部分。