名为i的变量是不可接受的吗?
就变量命名约定而言,迭代器是否应命名为" i"或者更像" count"这样的语义?如果我们不使用i
,为什么不呢?如果我们认为i
是可以接受的,那么在某些迭代情况下不应该使用它吗?
解决方案
如果我们命名它描述了正在循环通过的内容,那么它会有所帮助。但是我通常只使用i。
我绝对可以接受。不知道我需要提出什么样的理由-但是我一直都在使用它,其他受人尊敬的程序员也是如此。
社会验证,我想:)
是的,事实上,它是首选,因为任何阅读代码的程序员都会理解,它只是一个迭代器。
只要我们使用i来计数循环,或者使用从0(或者1,取决于PL)到n的索引的一部分,那么我会说我很好。
否则,它可能很容易命名,而不仅仅是索引。
如果"更多语义"是"迭代器",则没有理由不使用i;否则,将不再使用i。这是一个很好理解的成语。
" i"表示程序员的"循环计数器"。没有错。
我倾向于将i,j,k用于非常局部的循环(就源代码行的数量而言,仅存在很短的时间)。对于存在于较大源区域的变量,我倾向于使用更详细的名称,以便无需搜索代码即可查看它们的用途。
顺便说一句,我认为它们的命名约定来自早期的Fortran语言,在那里我是第一个整数变量(AH是浮点数)?
这是完全没问题的另一个示例:
foreach (Product p in ProductList) { // Do something with p }
我应该指出,i和j也是矩阵索引的数学符号。通常,我们正在遍历数组。因此,这是有道理的。
取决于我猜想的上下文。如果我们在某些对象中遍历一组对象
集合,那么从上下文中应该很明显地知道我们在做什么。
for(int i = 0; i < 10; i++) { // i is well known here to be the index objectCollection[i].SomeProperty = someValue; }
但是,如果从上下文中不能立即得知我们在做什么,或者如果我们要对索引进行修改,则应该使用一个更能说明其用法的变量名。
for(int currentRow = 0; currentRow < numRows; currentRow++) { for(int currentCol = 0; currentCol < numCols; currentCol++) { someTable[currentRow][currentCol] = someValue; } }
只要我们在一个简单的循环中临时使用它,就可以肯定我们在做什么。就是说,我们可以使用其他简短词代替吗?
" i"被广泛称为循环迭代器,因此,如果在循环之外使用它,实际上会使维护程序员感到困惑,但是如果使用更具描述性的东西(例如" filecounter"),它会使代码变得更好。
可以肯定地说," i"是可以接受的。但是,我有一个学期的C ++老师从一个学期学到了很多东西,他拒绝了每个变量都没有描述性名称的代码。用描述性方式命名所有内容的简单行为迫使我对代码进行了更加认真的思考,并且在该课程结束后,我编写了更好的程序,而不是学习C ++,而是学习了命名一切。 Code Complete在同一主题上也有很好的用语。
使用i而不是更具体的变量名的值是什么?要节省1秒钟或者10秒钟,或者也许甚至30秒钟的思考和打字时间?
使用i的费用是多少?也许什么都没有。也许代码是如此简单,以至于使用i就可以了。但是也许,也许,使用i会迫使将来使用此代码的开发人员不得不思考一会儿"我在这里意味着什么?"。他们将不得不思考:"这是一个索引,一个计数,一个偏移量,一个标志吗?"他们将不得不思考:"此更改安全吗?是否正确?我会被减一吗?"
使用i可以节省编写代码时的时间和精力,但将来可能会花费更多的精力,甚至可能由于误解代码而导致缺陷的无意引入。
一般来说,大多数软件开发都是维护和扩展,因此花费在读取代码上的时间将大大超过编写代码所花费的时间。
养成在任何地方都使用有意义的名称的习惯非常容易,一旦习惯,使用有意义的名称编写代码只需要几秒钟的时间,但随后代码将变得更易于阅读,易于理解等等。显然是正确的。
我用我短循环。
可以的原因是,我发现有人可以看到带有初始化器的迭代器类型的声明,这是完全不可行的,然后三行随后声称尚不清楚变量代表什么。他们只是假装,因为他们已经决定"有意义的变量名"必须表示"长变量名"。
我之所以这样做,是因为我发现使用与手头特定任务无关的东西,而且我只会在很小的范围内使用,这让我担心我可能使用的名称具有误导性,歧义性,或者有一天将对更大范围的其他事情有用。它之所以是" i"而不是" q"或者" count"的原因仅仅是从数学中借来的惯例。
我不使用我,如果:
- 循环体不小,或者
- 迭代器除了执行从范围开始到循环结束的前进(或者后退)以外,不执行其他任何操作:
只要增量是一致且清晰的,我不一定就必须以1为增量,并且当然可以在iterand结束之前停止,但是如果它改变了方向或者未被循环迭代所修改(包括在正向循环中对iterator.insertAfter()的恶意使用),我尝试记住要使用其他方法。这表明"这不仅仅是一个琐碎的循环变量,因此这可能不是琐碎的循环"。
这取决于。
如果我们要遍历某些特定数据集,那么我认为使用描述性名称更有意义。 (例如Dan建议的filecounter
)。
但是,如果我们执行任意循环,则可以接受" i"。正如一个同事向我描述的那样," i"是一个约定,意思是"此变量只能由for
循环结构修改。如果不是,请不要使用" i"。
在INTEGER循环计数器中使用i,j,k可以追溯到FORTRAN的早期。
就我个人而言,只要它们是整数计数,我对它们就没有问题。
但是后来我在FORTRAN上长大了!
我很好,但是这样的事情不是:
for (int i = 0; i < 10; i++) { for (int j = 0; j < 10; j++) { string s = datarow[i][j].ToString(); // or worse } }
对于程序员而言,无意间交换代码中的i和j非常普遍,尤其是在视力不好或者Windows主题为"热狗"的情况下。对我而言,这始终是一种"代码异味",当这种情况不为所动时,这种情况很少见。
我是如此普遍以至于可以接受,即使对于喜欢描述性变量名的人也是如此。
绝对不可接受的(在我的书中是一个罪过)是在循环中将i,j或者k用作整数索引之外的任何其他情况。
foreach(Input i in inputs) { Process(i); }
我认为在循环情况下我是完全可以接受的。我一直发现这是非常标准的,在这种情况下使用i时从来没有真正遇到过解释问题。 foreach循环会变得有些棘手,我认为这实际上取决于情况。我很少在foreach中使用过i,仅在for循环中使用过,因为在这些情况下,我发现我的描述性太低了。对于foreach,我尝试使用被循环对象类型的缩写。例如:
foreach(DataRow dr in datatable.Rows) { //do stuff to/with datarow dr here }
无论如何,只要$ 0.02.
我的感觉是,对于"简单"循环,使用单个字母的概念很好,但是,我很久以前就学会了使用双字母,并且效果很好。
上周我问了一个类似的问题,以下是我自己的答案的一部分:
// recommended style ● // "typical" single-letter style ● for (ii=0; ii<10; ++ii) { ● for (i=0; i<10; ++i) { for (jj=0; jj<10; ++jj) { ● for (j=0; j<10; ++j) { mm[ii][jj] = ii * jj; ● m[i][j] = i * j; } ● } } ● }
以防万一好处不那么明显:在代码中搜索任何单个字母都会发现很多我们不想要的东西。字母" i"在代码中不是我们要查找的变量中经常出现。
我已经这样做了至少10年。
请注意,很多人都评论说以上两种情况都是"丑陋的" ...
我要反对事实,说不。
对于说" i被理解为迭代器"的人群,这可能是正确的,但对我来说,这相当于"将值5分配给变量Y"这样的注释。变量名称(例如comment)应说明原因/不如何。
要使用先前答案中的示例,请执行以下操作:
for(int i = 0; i < 10; i++) { // i is well known here to be the index objectCollection[i].SomeProperty = someValue; }
像这样使用一个有意义的名称难吗?
for(int objectCollectionIndex = 0; objectCollectionIndex < 10; objectCollectionIndex ++) { objectCollection[objectCollectionIndex].SomeProperty = someValue; }
授予(借用的)变量名称objectCollection的名称也很错误。