bucket-sort logo bucket-sort

プログラミングとインフラエンジニアリングの覚え書き

  • Posts
  • About
  • Contact
  1. Home
  2. All Posts
  3. [C#] CIL で型とメンバーがどう表現されるか

[C#] CIL で型とメンバーがどう表現されるか

Jul 12, 2026 C# , .NET bucket-sort

前回は、CIL を読む理由と基本的なスタック動作を見ました。

今回は、CIL で型やメンバーがどのように表現されるかを確認します。
C# のクラス、インターフェイス、構造体、列挙型、ジェネリック型、フィールド、コンストラクター、プロパティが、CIL 上ではどのような宣言になるのかを見ていきます。

外部アセンブリの参照

CIL では、外部アセンブリへの参照を宣言できます。

.assembly extern System.Runtime
{
  .ver 8:0:0:0
}

これは「このアセンブリは System.Runtime を参照している」という情報です。
C# のプロジェクト参照や NuGet パッケージ参照が、ビルド後にはアセンブリ参照としてメタデータに記録されます。

現在のアセンブリを定義する

現在作っているアセンブリ自身も宣言されます。

.assembly SampleLibrary
{
  .ver 1:0:0:0
}

アセンブリ名やバージョンは、実行時の読み込みや依存関係解決に関わります。

リフレクションで見ると、次のような情報として取得できます。

using System.Reflection;

Assembly assembly = Assembly.GetExecutingAssembly();
AssemblyName name = assembly.GetName();

Console.WriteLine(name.Name);
Console.WriteLine(name.Version);

名前空間とクラス

C# では名前空間とクラスを次のように書きます。

namespace SampleLibrary;

public class Calculator
{
    public int Add(int x, int y)
    {
        return x + y;
    }
}

CIL では、名前空間を含んだ型名として表現されます。

.class public auto ansi beforefieldinit SampleLibrary.Calculator
       extends [System.Runtime]System.Object
{
}

名前空間専用のブロックがあるというより、型の完全名に名前空間が含まれると考えると分かりやすいです。

インターフェイス

C# のインターフェイスです。

public interface ICalculator
{
    int Add(int x, int y);
}

概念的な CIL では、次のようになります。

.class interface public abstract auto ansi ICalculator
{
  .method public hidebysig newslot abstract virtual
          instance int32 Add(int32 x, int32 y) cil managed
  {
  }
}

インターフェイスのメソッドは、実装を持たない抽象的な契約として表現されます。

クラスがインターフェイスを実装する場合は、型宣言に実装情報が含まれます。

.class public auto ansi beforefieldinit Calculator
       extends [System.Runtime]System.Object
       implements ICalculator
{
}

構造体

C# の構造体です。

public struct Point
{
    public int X { get; set; }
    public int Y { get; set; }
}

CIL では、構造体は System.ValueType を継承する型として表現されます。

.class public sequential ansi sealed beforefieldinit Point
       extends [System.Runtime]System.ValueType
{
}

C# では構造体がクラスと別の構文になっていますが、メタデータ上は値型として特別な基底型を持つ型です。

列挙型

C# の列挙型です。

public enum EngineState
{
    Stopped,
    Running,
    Broken
}

CIL では、System.Enum を継承する型として表現されます。

.class public auto ansi sealed EngineState
       extends [System.Runtime]System.Enum
{
  .field public specialname rtspecialname int32 value__
  .field public static literal valuetype EngineState Stopped = int32(0)
  .field public static literal valuetype EngineState Running = int32(1)
  .field public static literal valuetype EngineState Broken = int32(2)
}

列挙値は、静的なリテラルフィールドとして表現されます。

ジェネリック型

C# のジェネリック型です。

public class Box<T>
{
    public T Value { get; set; } = default!;
}

概念的な CIL では、型引数を持つクラスとして表現されます。

.class public auto ansi beforefieldinit Box`1<T>
       extends [System.Runtime]System.Object
{
  .field private !T '<Value>k__BackingField'
}

Box の後ろに付く `1 は、型引数が 1 つあることを表します。
!T は、型引数 T を表します。

ジェネリックは C# の表面構文では読みやすく書けますが、CIL では型引数の個数や型パラメーターが明示されます。

フィールド

C# のフィールドです。

public class Counter
{
    private int count;
}

CIL では次のように表現されます。

.field private int32 count

自動プロパティを使った場合も、内部的にはバッキングフィールドが生成されます。

public string Name { get; set; } = "";

概念的には次のようなフィールドが作られます。

.field private string '<Name>k__BackingField'

コンストラクター

C# のコンストラクターです。

public class Person
{
    public string Name { get; }

    public Person(string name)
    {
        Name = name;
    }
}

CIL では、コンストラクターは .ctor という特別な名前のメソッドとして表現されます。

.method public hidebysig specialname rtspecialname
        instance void .ctor(string name) cil managed
{
  ldarg.0
  call instance void [System.Runtime]System.Object::.ctor()

  ldarg.0
  ldarg.1
  stfld string Person::'<Name>k__BackingField'

  ret
}

ldarg.0 は、インスタンスメソッドでは this を表します。
コンストラクターでは、まず基底クラスのコンストラクターを呼び、その後フィールドへ値を設定します。

プロパティ

C# のプロパティです。

public string Name { get; set; } = "";

CIL 上では、プロパティ本体そのものというより、取得メソッドと設定メソッドが定義されます。

.property instance string Name()
{
  .get instance string Person::get_Name()
  .set instance void Person::set_Name(string)
}

取得メソッドと設定メソッドは、通常のメソッドとしても表現されます。

.method public hidebysig specialname
        instance string get_Name() cil managed
{
  ldarg.0
  ldfld string Person::'<Name>k__BackingField'
  ret
}

プロパティは C# ではフィールドのように見えますが、実際にはメソッド呼び出しとして表現される点が重要です。

引数情報

メソッド引数もメタデータとして記録されます。

public void Move(int x, int y)
{
}

概念的には、次のようなメソッドシグネチャになります。

.method public hidebysig instance void Move(int32 x, int32 y) cil managed
{
  ret
}

引数名はデバッグ情報やメタデータに含まれる場合があります。
リフレクションでは次のように取得できます。

using System.Reflection;

MethodInfo method = typeof(Person).GetMethod("Move")!;

foreach (ParameterInfo parameter in method.GetParameters())
{
    Console.WriteLine($"{parameter.ParameterType.Name} {parameter.Name}");
}

C# と CIL の対応を読む意義

CIL の型定義を読むと、C# の便利な構文がどのように展開されるかが見えてきます。

  • プロパティは取得/設定メソッドとして表現される
  • 自動プロパティにはバッキングフィールドが生成される
  • コンストラクターは .ctor という特別なメソッドになる
  • 構造体は System.ValueType を継承する
  • 列挙型は System.Enum を継承し、列挙値はフィールドになる
  • ジェネリック型は型引数の個数を含む名前で表現される

これらを知っておくと、リフレクションで見える情報の意味が理解しやすくなります。

まとめ

CIL では、C# の型やメンバーがメタデータとして明示的に表現されます。
クラス、インターフェイス、構造体、列挙型、ジェネリック型、フィールド、コンストラクター、プロパティは、それぞれ CIL 上の宣言に変換されます。

次回は、CIL の命令に注目し、ローカル変数、引数、this、ループ、ラベル、スタックサイズなどを読み解きます。

C# .NET CIL IL 型 メタデータ ジェネリック
← [C#] CIL を読む理由と基本文法を理解する [C#] CIL の命令とスタック動作を読み解く →

Related Posts

  • [C#] CIL の命令とスタック動作を読み解く Jul 13, 2026
  • [C#] CIL を読む理由と基本文法を理解する Jul 11, 2026
  • [C#] リフレクションで型の中身を調べる Jul 6, 2026
  • [C#] .NET アセンブリの構造とライブラリの種類を理解する Jul 1, 2026

Table of Contents

  • 外部アセンブリの参照
  • 現在のアセンブリを定義する
  • 名前空間とクラス
  • インターフェイス
  • 構造体
  • 列挙型
  • ジェネリック型
  • フィールド
  • コンストラクター
  • プロパティ
  • 引数情報
  • C# と CIL の対応を読む意義
  • まとめ

Recent Posts

  • [C#] EF Core でデータベースの準備と初期データを扱う Aug 8, 2026
  • [C#] EF Core とリポジトリでデータ操作を整理する Aug 7, 2026
  • [C#] DbContext の設定と保存処理を拡張する Aug 6, 2026
  • [C#] EF Core のエンティティと表示用モデルを設計する Aug 5, 2026
  • [C#] EF Core を中心にデータアクセス層を分ける Aug 4, 2026

Categories

  • C#150
  • .NET149
  • AWS27
  • Laravel16
  • Entity Framework Core15
  • Linux15
  • MySQL9
  • Apache8
  • PHP8
  • Data Access6
  • DynamoDB6
  • セキュリティ6
  • Nginx5
  • WordPress4
  • インフラ4
  • Hugo3
  • .NET Framework1
  • Aurora1
  • Diagnostics1
  • Filament1

Tags

  • C#
  • .NET
  • AWS
  • Laravel
  • コレクション
  • PHP
  • Entity Framework Core
  • セキュリティ
  • MySQL
  • Linux
  • パフォーマンス
  • Apache
  • LINQ
  • System.Collections.Generic
  • デリゲート
  • リフレクション
  • ADO.NET
  • Code Snippet
  • DynamoDB
  • NoSQL
  • PHP-FPM
  • RDS
  • System.Collections
  • Windows
  • メタデータ
  • メモリ管理
  • CIL
  • DoS
  • Nginx
  • SQL Server
  • WordPress
  • ラムダ式
  • 監視
  • 設計
  • Amazon Linux 2023
  • Delegate
  • Docker
  • IDisposable
  • Ipset
  • Iptables
  • LINQ to Objects
  • OPCache
  • Pointer
  • Reflection
  • System.Collections.Specialized
  • Unsafe
  • Webサーバー
  • アセンブリ
  • インターフェース
  • オブジェクト指向
Powered by Hugo & Explore Theme.