は
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
が 0 未満の場合は、それにインデックスをarr
付けません。
k
while ループの本体が正しく減少せず、無限ループにつながる可能性があるため、安全ではない可能性があります。または、 がの境界k
を超えている場合は安全ではない可能性があります。arr
配列のサイズにも注意する必要があります。
while (k >= 0 && k < arr.length && arr[k] > 0)
より安全なコードになります。
はい、これは良い習慣です。&&
実際、これが短絡演算子が発明された理由の一部です 。演算子はその部分式を左から右に評価し、偽の部分式を見つけると停止します。これはまさにあなたが望むものです。演算子を使用すると、&&
これを 1 行で表現できます。
表現について:
while (k >= 0 && arr[k] > 0) { ... }
いいえ、安全ではありません。
式は、 の正のインデックスのみが使用されるk >= 0 && arr[k] > 0
ことを保証するという点で安全です(これらの場合、 およびのショートカット値は2 番目のオペランドを評価しないため)。arr[k]
&&
k < 0
arr[k] > 0
ただし、インデックスが境界を超えていることは保証されていないことに注意してください(たとえば、)。 arr も可能性があります。したがって、またはのいずれかを取得できます。処理しないと、アプリケーションが壊れます。k >= arr.length
null
IndexOutOfRangeException
NullReferenceException
それを避けるには、
if (k >=0 && arr != null)
{
while (k<arr.Length && arr[k] > 0) { ... k++; }
}
上記のコードでは、 arr
isnull
の場合、配列に要素がないため、ループをスキップできます。配列の長さを超えた場合 (つまり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
false
true
ただし、場合によっては、 「非ショートカット」バージョン&
も必要になります。次の例のように、文字列配列を整数の配列に変換し、整数に変換できない値 (その他は 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();
}
このコードの目的は、文字列配列の値を 1 つずつ 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]
ます。
これは意図しない副作用であり、( を使用して&
) すべての式を評価するように強制することで修正できます。