値型
構造体、列挙体、数値型、boolが該当します。
インスタンスはマネージスタックに確保されます。
値型の変数は値自体を保持します。なので、値型の変数を別の変数に代入すると値がコピーされます。
構造体はSystem.ValueTypeから暗黙的に派生し、列挙体はSystem.Enumから暗黙的に派生します。
namespace SuperclassTest { // 列挙体は明示しないが暗黙的にSystem.Enumを継承 enum EnumTest { val0, val1 } // 構造体は明示しないが暗黙的にSystem.ValueTypeを継承 struct StructTest { int val0; long val1; } class Program { static void Main(string[] args) { } } }
ILDasmでMethodInfoをダンプすると
TypeDef #1 (02000002) ------------------------------------------------------- TypDefName: SuperclassTest.EnumTest (02000002) Flags : [NotPublic] [AutoLayout] [Class] [Sealed] [AnsiClass] (00000100) Extends : 01000001 [TypeRef] System.Enum TypeDef #2 (02000003) ------------------------------------------------------- TypDefName: SuperclassTest.StructTest (02000003) Flags : [NotPublic] [SequentialLayout] [Class] [Sealed] [AnsiClass] [BeforeFieldInit] (00100108) Extends : 01000002 [TypeRef] System.ValueType
となっています。
値型から新しい型を派生することはできません。(但しインターフェースの実装はできます)
using System; namespace InheritsTest { class Program { // これはコンパイルエラー // エラー CS0527: インターフェイス リストの型 'int' はインターフェイスではありません。 //private struct StructTest : int //{ //} // これはインターフェースの実装なので問題ない private struct StructTest : IDisposable { #region IDisposable メンバー public void Dispose() { throw new NotImplementedException(); } #endregion } static void Main(string[] args) { } } }
値自体を保持するので値型は暗黙的にコンストラクタを持ち、宣言時に値が初期化されます。(なので、コンストラクタは1つ以上の引数を取るものしか宣言できません)
namespace ConstructorTest { class Program { private struct StructTest { int _i; // これはコンパイルエラー // CS0568: 構造体に明示的なパラメーターのないコンストラクターを含めることはできません。 //public StructTest() { this._i = 0; } // これはオーバーロードなので問題ない public StructTest(int val) { this._i = val; } } static void Main(string[] args) { } } }
定数式のオペランドが全て単純型の定数の場合、式はコンパイル時に解決されます。
using System; namespace ConstTest { class Program { const int val1 = 1; const int val2 = 2; const int val3 = 3; static void Main(string[] args) { Console.WriteLine(val1 + val2 + val3); } } }
ILDasmで逆アセンブルすると該当のMainメソッドの内容は
.method private hidebysig static void Main(string[] args) cil managed { .entrypoint // コード サイズ 9 (0x9) .maxstack 8 IL_0000: nop IL_0001: ldc.i4.6 IL_0002: call void [mscorlib]System.Console::WriteLine(int32) IL_0007: nop IL_0008: ret } // end of method Program::Main
となります。IL_0001で評価後の値がリテラルとして設定されています。