9

如果找到,该方法List<T>.IndexOf()返回整个 List 中第一次出现的 item 的从零开始的索引;否则,–1

我看到了这与我刚刚在Code Complete中读到的内容之间的相似之处,这告诉我“避免使用具有隐藏含义的变量”。

例如:变量 pageCount 中的值可能表示打印的页数,除非它等于 -1,在这种情况下,它表示发生了错误。

好吧,我不知道意思是否“隐藏”,因为它的记录足够清楚,但null似乎比-1向我传达了更好的含义,而且.HasValue读起来比> -1更好。据我所知,List 和可为空的类型都是在 C# 2.0 中引入的,所以我认为重新调整 an 的原因int与向后兼容性无关。那么,您知道是否有原因,或者这是否只是某人忘记实施的事情,而我们现在必须永远忍受这个错误?

4

6 回答 6

10

List 与 2.0 版本的运行时一起发布,T 也是可空的。但 List 实现了IList,它与 1.0 版本的运行时一起存在,它不仅没有可空而且不支持泛型。为了满足 IList 接口的约定,实现者必须在 indexof 失败时返回 -1。Code complete 还认为您必须满足您同意的合同,因此 List.Indexof 必须返回 -1。


回复评论:

到带有泛型的 2.0 运行时,已经有数千个针对非泛型版本编写的应用程序。通过支持泛型接口作为非泛型接口的扩展,可以最有效地迁移该代码。此外,图像必须具有相同名称和 90% 相同用法的类,但在几个方法的情况下,语义完全不同。

于 2012-06-02T18:49:17.793 回答
6

System.Collections.Generic.List可能已经在 .NET 2.0 中引入,以及可为空的,但 -1 的使用早于它。 ArrayList.IndexOf(), Array.IndexOf(), String.IndexOf(),SelectedIndex列表框等。所以List<T>很可能为了与现有库保持一致而做了同样的事情。(事实上​​,即使是经典的 VB 也有这个含义,所以它甚至早于 .NET 1.0)

正如@rerun指出的那样,这不仅仅是风格上的一致性,它实际上是接口契约的一部分。所以给他+1。

虽然List<T>不必跟随ArrayList也不必实现IList,但这样做对于已经熟悉这些的程序员来说更加有用。

于 2012-06-02T18:47:33.550 回答
2

只是一个猜测,但我认为这与历史原因和可读性有关。即使 -1 是一个“特殊值”,它也不会在任何其他情况下返回。我认为您引用的规则主要是为了防止您返回可能具有多个含义的值。-1 在 c++ 和类似语言中是标准的,因此它在某种程度上已成为跨语言的习惯用法。此外,虽然 hasvalue 可能更具可读性,但我认为最好在整个框架中保持一致的风格,这需要从头开始。最后,恕我直言,以我有限的经验,因为必须将可空类型拆箱才能在其他地方使用它们,它们可能比它们的价值更麻烦,但这只是我。

于 2012-06-02T19:12:39.840 回答
1

我认为这是为了向后兼容,因为在框架 1.1 中没有可空值,并且当时创建了 API。

于 2012-06-02T18:46:22.703 回答
1

原因可能是一个简单的事实,即Nullable<T>(您编写时使用的实际类型T?)对于像索引搜索这样简单的事情涉及不必要的复杂性。因为T? xx == null实际上只是语法糖x.HasValue,当事实证明它不是null你仍然必须通过x.Value.

与仅返回一个负值相比,您并没有真正获得任何东西,这也不是一个有效的索引。事实上,你让事情变得更加复杂。

于 2012-06-02T18:56:59.337 回答
0

这遵循与 相同的模式String.IndexOf,以及许多其他实现和IndexOf方法的变体,不仅在 .NET 库中。

使用 -1 作为返回值是一个神奇的数字,通常应该避免使用。但是,这种模式是众所周知的,当您实现库方法时,这显然是一个优势。

于 2012-06-02T18:50:47.870 回答