是
while (k >= 0 && arr[k] > 0)
安全的?
当 k 在范围内并且 arr[k] > 0 时它会循环。但我不知道这是否是编码的好习惯。我知道如果我们这样做
while (arr[k] > 0 && k >= 0)
这将是一场灾难。
是
while (k >= 0 && arr[k] > 0)
安全的?
当 k 在范围内并且 arr[k] > 0 时它会循环。但我不知道这是否是编码的好习惯。我知道如果我们这样做
while (arr[k] > 0 && k >= 0)
这将是一场灾难。
&&短路是安全的。如果k小于零,则不会对其进行索引arr。
这可能是不安全的,因为您的 while 循环体可能不会k正确递减,从而导致无限循环。k或者如果超出arr's bounds可能不安全。
您还应该关心数组大小:
while (k >= 0 && k < arr.length && arr[k] > 0)
将是一个更安全的代码。
是的,这是一个很好的做法。事实上,这也是发明短路 &&算子的部分原因。运算符从左到右计算其子表达式,并在找到错误的子表达式时停止。这正是您想要的;运算符&&允许您在一行中表达这一点。
关于表达:
而 (k >= 0 && arr[k] > 0) { ... }
不,这不安全。
该表达式k >= 0 && arr[k] > 0在某种程度上是安全的,它确保仅arr[k]使用正索引 of (因为在这些情况下,不会评估第二个操作数&&的快捷方式值)。k < 0arr[k] > 0
但请注意,不能保证索引超出范围(例如 for k >= arr.length) - 并且 arr 也可能是null。因此,您可以获得一个IndexOutOfRangeException或一个NullReferenceException- 如果未处理,您的应用程序将中断。
为避免这种情况,请使用
if (k >=0 && arr != null)
{
while (k<arr.Length && arr[k] > 0) { ... k++; }
}
在上面的代码中,如果arr是null,则可以跳过循环,因为数组中没有元素。如果超出数组长度(即k>=arr.length),则arr[k] > 0不再检查(从而避免发生异常)。
我已将表达式的不变部分k >=0 && arr != null从循环表达式中取出,因为没有必要(并且运行速度会更慢)在循环的每次迭代中对其进行评估。
与for循环相同:
if (k >=0 && arr != null)
for (; var k=0; k<arr.Length && arr[k] > 0; k++) { ... }
请注意,因为您不是从 0 开始,所以我跳过了初始化var k=0,我假设您已经在源代码的上方某处完成了初始化。
除此之外,还有一些附加信息- 如果您想了解有关逻辑运算符和副作用的一些有趣细节,请继续阅读。
在C/C++/C#&中,重要的是要知道vs.&&和|vs. ||:之间的区别,&并|“按位”评估整个表达式,而&&如果||结果已经清楚则停止评估(如果有任何部分,逻辑and不能是true表达式是;如果表达式的任何部分是 ),则false逻辑or不能是)。falsetrue
但是,在某些情况下,您也需要“非快捷方式”版本&。假设您想要将字符串数组转换为整数数组,并且您想要转换每个可以转换的值,即使有些值不能转换为整数(其他值应保持 0) - 如下例所示:
void Main()
{
var sArr = new string[] {"4", "2", "x", "y", "10", "11"};
var iArr = new int[sArr.Length];
bool bCheck = true;
for (var i=0; i<sArr.Length; i++)
{
int value=0;
// need to use & instead of && here:
bCheck = bCheck && int.TryParse(sArr[i], out value);
iArr[i]=value;
};
if (bCheck==true)
{
Console.WriteLine("All numbers are okay.");
}
foreach (var n in iArr) Console.Write(n.ToString() + " ");
Console.WriteLine();
}
此代码的目的是将字符串数组中的值一一转换为 int 并将它们存储在整数数组中 - 如果元素不包含有效整数,则它存储值 0 代替。
我们在这里得到的输出是
4 2 0 0 0 0
这不是我们所期望的,因为 10 和 11 也是有效的整数并且应该被转换,相反我们得到了它们的 0 和 0。
为了得到我们期望的结果,即
4 2 0 0 10 11
我们需要替换&&为&:
bCheck = bCheck & int.TryParse(sArr[i], out value);
这里有什么区别?
如果您在&&上面的语句中使用,那么只要 bCheck 计算结果为 false,快捷方式就会完成——这通常是正确的,因为这样我们就不必再检查表达式了,因为不可能被计算为 true .
但也会发生的情况是,由于我们有快捷方式,int.TryParse不再被调用,因此值不会从函数中传递出去——循环中的所有后续调用都将评估为 0,而不管sArr[i].
这是我们在这里遇到的意外副作用,可以通过强制评估每个表达式来修复(通过使用&)。