available LDC instructionsを見ると、何が起こっているのかを簡単に知ることができます。使用可能なオペランドタイプの限定されたセットに注意してください。バージョンがあり、short型の定数をロードできます。ちょうどint、long、float、double。これらの制限は他の場所で見ることができます。例えば、Opcodes.Add命令は同様に制限されており、より小さな型の変数を追加することはできません。
IL命令セットは意図的にこのように設計されており、単純な32ビットプロセッサの機能を反映しています。考えるべきプロセッサの種類はRISCの種類であり、彼らは19世紀の彼らの乾草期を迎えました。 32ビット整数とIEEE-754浮動小数点型のみを操作できる32ビットCPUレジスタがたくさんあります。 Intel x86コアは良い例ではありませんが、非常に一般的に使用されていますが、実際には8ビットと16ビットのオペランドの読み込みと演算をサポートするCISCデザインです。しかしこれは歴史的な事故であり、8ビットの8080と16ビットの8086プロセッサーから始まるプログラムの機械的な翻訳を簡単にしました。しかし、このような機能は無償で提供されるわけではなく、16ビットの値を操作すると実際に余分なCPUサイクルがかかります。
ILを32ビットプロセッサの機能とよくマッチさせることで、明らかにジッタを実装するユーザーの仕事がはるかに簡単になります。ストレージの場所はまだ小さくてもかまいませんが、ロード、ストア、および変換のみをサポートする必要があります。そして、必要なときだけ、あなたの 'a'変数はローカル変数です。スタックフレームまたはCPUレジスタに32ビットを占有する変数です。メモリへのストアのみを適切なサイズに切り捨てる必要があります。
そうでなければ、コードスニペットにあいまいさはありません。 Marshal.SizeOf()はオブジェクトの型の引数を取るため、変数値を囲む必要があります。ボックス化された値は、型ハンドルによって値の型を識別し、System.Int16を指します。 Marshal.SizeOf()には、2バイトかかることを知るビルトイン知識があります。
これらの制限はC#言語に反映され、矛盾を引き起こします。コンパイルエラーのこの種のは、永遠のC#プログラマをbefuddlesと悩ま:
IL制限の結果である
byte b1 = 127;
b1 += 1; // no error
b1 = b1 + 1; // error CS0266
、バイトのオペランドを取り全く追加演算子はありません。この場合は、次に大きい互換性のあるタイプintに変換する必要があります。したがって、32ビットRISCプロセッサで動作します。今問題がありますが、32ビットののの結果を8ビットしか格納できない変数に戻す必要があります。 C#言語では、最初の割り当てでハンマー自体が適用されますが、2番目の割り当てでは非形式的にキャストハンマーが必要です。
メモリ内のサイズは、配列などのより大きな構造に埋め込む場合にのみ意味のある概念です。ローカル変数を持っているときは、それが単なる1バイトであっても、通常は完全なレジスタ(AMD64では64ビット)を占有します。 C#コンパイラはInt32を内部的に使用します。これは、観察された動作がInt16の動作と一致する限り、権利の範囲内にあるほとんどのものに対して内部的に使用されます。 – CodesInChaos
@CodesInChaos 32ビットで4バイトかかるのですか?もしそうなら、なぜsieOfに2が表示されますか? –
サイズは2のように定義されており、2バイトで十分です。しかし、もしあなたがローカル変数を持っていれば、それはコンパイラ/ JITerが望むだけ多くのバイトを要します。プログラムの動作が影響を受けていない限り、彼らは好きなことを自由に行うことができます。多くの場合、メソッドの実行中に単一のローカル変数が別の場所に格納されます。あなたのケースでは、 'a'を完全に排除し、単純に' 2'を定数として使うことさえあります。 – CodesInChaos