12

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

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

是否有一个更简单的解决方案,至少在 C++、C# 和 Java 的编译时检查静态越界赋值?某种静态断言

编辑:我知道“范围”可以用于不同的目的:

  1. 迭代器
  2. 枚举器
  3. 整数子类型

我会关注后者,因为前者很容易映射到 C* 语言上。我考虑一组封闭的值,比如音乐音量,即从 1 到 100 的范围。我想增加或减少一个值。我想在静态溢出的情况下出现编译错误,例如:

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

谢谢。

4

11 回答 11

3

Java 从 1.4 版开始就有了 assert 关键字。如果您通过合同进行编程,您可以自由地使用它们来检查正确的分配。并且在设置之前应检查对象内应落在特定范围内的任何可变属性。您也可以抛出 IllegalArgumentException。

为什么没有范围类型?我的猜测是,最初的设计者没有在 C++ 中看到它,并且认为它不像他们试图正确处理的其他功能一样重要。

于 2009-01-29T11:03:04.673 回答
3

子范围类型在实践中实际上并不是很有用。我们不经常分配固定长度的数组,也没有理由分配固定大小的整数。通常在我们确实看到固定大小的数组时,它们充当枚举,我们对此有更好的(尽管“更重”)的解决方案。

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

(必须提到整数在任何合理的语言中都应该是任意大小。)

于 2009-01-29T12:04:49.323 回答
3

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

于 2009-01-29T16:05:47.730 回答
2

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

它主要是一个带有额外类型检查的整数。您可以使用课程以其他语言伪造它。这提供了可以应用更复杂范围的优势。

于 2009-01-29T11:22:12.623 回答
2

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

于 2009-01-29T16:29:43.970 回答
1

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

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

boost::type_traits和 boost::mpl 可能是你最好的朋友来实现这样的东西。

于 2009-01-29T16:18:39.373 回答
1

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

MyRange<0,100> volume = 99;
volume += 10; // results in volume==100
于 2009-01-30T21:26:57.083 回答
1

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

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

于 2009-01-30T21:45:09.807 回答
1

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

IntRange ir = new IntRange(1, 10);

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

于 2010-07-26T21:00:49.050 回答
0

在 C# 中,您可以这样做:

foreach(int i in System.Linq.Enumerable.Range(0, 10))
{
    // Do something
}
于 2009-01-29T11:26:50.883 回答
0

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

于 2009-01-30T20:37:09.493 回答