インデックスによって配列またはコレクションをループするときは、ほとんどInt32
の場合orを使用する必要があります (いや、 orInt64
を使用しても信用を得ることはできません)。UInt32
UInt64
効率が悪い最も明白な理由は、BCL にあるすべての配列インデックスとコレクション インデックスが s を取るため、s をインデックスとして使用しようとするコードでは常にInt32
暗黙的なキャストが発生することです。Int16
それほど明白でない理由 (および配列がInt32
インデックスとして使用される理由) は、CIL 仕様で、すべての操作スタック値がまたはのいずれか であると規定されているためです。値を他の整数型 ( 、、、、または) にロードまたは格納するたびに、暗黙的な変換操作が行われます。符号なしの型には、ロードに対するペナルティはありませんが、値を格納する場合、これは切り捨てとオーバーフロー チェックの可能性があります。署名された型の場合、すべてのロードで符号が拡張され、すべてのストアで符号が折りたたまれます (また、オーバーフロー チェックが行われる可能性があります)。Int32
Int64
Byte
SByte
UInt16
Int16
UInt32
UInt64
これが最も害を及ぼすのは、配列へのアクセスではなく、ループ自体です。たとえば、次の無害に見えるループを見てみましょう。
for (short i = 0; i < 32000; i++) {
...
}
良さそうですよね?いいえ!基本的に初期化 ( short i = 0
) は 1 回しか発生しないため無視できますが、比較 ( i<32000
) とインクリメント ( i++
) の部分は 32000 回発生します。これがマシンレベルでどのように見えるかについてのいくつかの疑似コードは次のとおりです。
Int16 i = 0;
LOOP:
Int32 temp0 = Convert_I16_To_I32(i); // !!!
if (temp0 >= 32000) goto END;
...
Int32 temp1 = Convert_I16_To_I32(i); // !!!
Int32 temp2 = temp1 + 1;
i = Convert_I32_To_I16(temp2); // !!!
goto LOOP;
END:
そこには32000回実行される3 つの変換があります。また、 orを使用するだけで完全に回避できた可能性があります。Int32
Int64
更新: コメントで述べたように、実際にこのトピックに関するブログ投稿を書きました.NET Integral Data Types And You