導入
[Obsolete]や[JsonPropertyName]のように、[...]でコードに付ける「メタ情報」が属性(Attribute)です。そして実行時に「この型にはどんなプロパティ・属性があるか」を調べる仕組みがリフレクションです。テストフレームワーク([Fact])やJSON変換、DIコンテナなど、実務のライブラリの多くがこの2つで動いています。
図解
flowchart LR
C["コードに [Author("Taro")] を付ける"] --> META["型にメタ情報が埋め込まれる"]
META -->|リフレクションで読む| RUN["実行時に属性やプロパティを取得"]
RUN --> USE["ライブラリが自動処理<br/>(テスト実行・JSON変換など)"]
サンプル
// typeof / GetType: 実行時に「型そのもの」を得る
Console.WriteLine("hello".GetType().Name); // String
Console.WriteLine(typeof(int).Name); // Int32
// 属性を読む: [Author("Taro")] のメタ情報を実行時に取り出す
var attr = (AuthorAttribute?)Attribute.GetCustomAttribute(
typeof(Report), typeof(AuthorAttribute));
Console.WriteLine(attr?.Name); // Taro
// リフレクションでプロパティ名を列挙する
foreach (var prop in typeof(Report).GetProperties())
Console.WriteLine(prop.Name); // Title
// --- 型と属性の定義 ---
[Author("Taro")]
class Report
{
public string Title { get; set; } = "";
}
// 属性は Attribute を継承して作る(名前の末尾 Attribute は付け方で省略できる)
class AuthorAttribute : Attribute
{
public string Name { get; }
public AuthorAttribute(string name) => Name = name;
}
- 属性は
[名前(...)]でコードに付けるメタ情報。自作するにはAttributeを継承する - リフレクションは
typeof/GetTypeで型情報を取り、GetProperties/GetCustomAttributeで中身を調べる - 使うときは
[Author("Taro")]のように、クラス名末尾のAttributeを省略できる - xUnitの
[Fact]、JSONの[JsonPropertyName]など、既に使ってきた属性の仕組みがこれ
演習
double x = 3.14;
// TODO: 変数 x の型名を出力してください(Double)
___
- 期待される出力:
Double
ヒント1を見る
x.GetType()で型を取り、.Nameで名前が得られます
ヒント2を見る
Console.WriteLine(x.GetType().Name);
まとめ
- 属性は
[...]で付けるメタ情報、リフレクションは実行時に型情報を読む仕組み typeof/GetType→GetProperties/GetCustomAttributeで中身を調べる- テスト・JSON・DIなど多くのライブラリがこの土台で動いている
次回: プログラムのメモリの使われ方とガベージコレクションです。