2008-08-08 29 views
77

なぜArray.Lengthはintであり、uintではないのですか?長さの値が決して負にならないので、これは私を悩ます(ほんの少し)。 なぜArray.Lengthは整数ではなく、整数ではない

はこれも

だから究極の質問は...あなたがint値を指定する とき、これは明示的にキャストする必要があるため、自分のクラスに長さプロパティのint型を使用するように私を余儀なくさ:無署名のint(uint)のための使用はありますか?マイクロソフトでさえそれらを使用していないようです。

+0

問題が発生しても、UIntに変更する必要があります。 – alan2here

+1

@ alan2ここでこのような変更を行うと、ほとんどすべてのコードが破損してしまいますので、私に尋ねれば起こりません! – Peter

答えて

0

通常、符号なしの値が明示的に必要な場合を除き、整数値には符号が付きます。それは彼らが使用されている方法です。私はその選択に同意しないかもしれませんが、それはまさにその方法です。

当分の間、典型的なメモリの制約により、配列や類似のデータ構造にUInt32の長さが必要な場合は、他のデータ構造も考慮する必要があります。バイトの配列で

、のInt32はあなたの値の2ギガバイトを与える

+13

"だがそれはそれだけである」 - いいえ、物事は決して彼らの方法ではありません。常にデザインの意思決定が行われており、なぜそれを求めているのですか?賛否両論から何かを学んだり、(場合によっては)デザイナーと議論を交わしたりするかもしれません。常に質問してください! :) –

1

Array.Lengthは符号なしで負のintに追加された場合、Array.Lengthはある時点で負の数に追加されるので、下位レベルでは単純化する必要があるかもしれないと思う補完)、厄介な結果になる可能性があります。

+0

例を挙げてください。 'uint lenght = 3; int x = -4; Console.WriteLine(x + lenght);'は-1を返します。 –

1

"究極の質問"に誰も答えられなかったようです。

私は、unsigned intの主な用途は外部システム(P/Invokeなど)との簡単なインターフェイスを提供し、.NETに移植されるさまざまな言語のニーズをカバーすることだと考えています。

+0

複数の小さい値を連結して大きな値を生成する場合、符号なしの型は不可欠です。 '(HighPart << 16)+ LowPart'を計算することによって2つのUInt16を組み合わせてUInt32を作ることができ、UInt32を'(Uint16)(Value >> 16) 'と'(Uint16)(Value &65535) 'このような操作は、「LowPart」が署名付きの型でなければならない場合、非常に不便である。言われていることは、署名型と署名なし型の間の相互作用は、しばしば混乱し問題が多いことです。署名のない型は、多くの点で独自の世界とみなされるべきです。 – supercat

45

多くの理由:

  • UINTは、このように本来設計が占有ヒープ上の任意のオブジェクトを禁止するように依存タイプに内蔵(アレイ)ランタイム
  • 問題があったであろう行う、CLSに準拠していません2GB以上のメモリこの限界以下の最大サイズの配列は新しいbyte [int.MaxValue]なので、正であるが不正な配列の長さを生成することができるのは困惑します。
  • 歴史的にC#は、CとC++の構文と規約の多くを継承しています。これらの配列では単純にポインタの算術演算であるため、負の配列インデックスが可能でした(通常は違法で危険ですが)。既存のコードでは配列インデックスが署名されていると仮定しているため、これは要素であったでしょう
  • 関連するメモでは、C/C++の配列インデックスに符号付き整数を使用すると、これらの言語と管理対象外関数を持つinteropは、とにかくそのような状況では、intは不一致のために混乱する可能性があります。
  • BinarySearchの実装(多くのアルゴリズムの非常に有用なコンポーネント)は、値が見つからないことを示すためにintの負の範囲を使用できることに依存しています。この値を維持するために挿入する場所ソート。
  • アレイ上で操作するときは、既存のインデックスの負のオフセットを取ることをお勧めします。 unitを使用して配列の先頭を過ぎてしまうオフセットを使用した場合、ラップアラウンド・ビヘイビアはインデックスが正当なものである可能性があります。 intを指定すると結果は不正になりますが、実行時に無効なメモリを読み取らないようにするため安全です。
+2

ヒープ上に何も2Gb以上になることができない場合、ほとんどの型は1バイトよりも大きいので、長さint.MaxValueの配列のほとんどすべては不正です。 – ScottS

+0

実際には((uint)(int.MaxValue))+ 1は* anything *に対して間違っていることが保証されます。 intはそれ自体完璧ではありませんが、物事のバランスによって型としてint型を保つことは合法です。 – ShuggyCoUk

+0

explict ArrayIndex型(本質的にsize_t)であれば、必要に応じてきれいに安全にintに変換することができます。将来的には痛みの少ない2GB以上の配列を使用できるようになります。しかし、Javaは同じ問題を抱えているので、なぜリスクを取るのかということについては、 – ShuggyCoUk

関連する問題