C#を使って開発をしていると、「今このインスタンスのクラス名を動的に取得したい」と思う場面に出くわすことがあります。ログ出力やデバッグ、さらにはフレームワーク開発や汎用ライブラリ作成の際など、クラス名の取得は非常に有用です。この記事では、GetType() や typeof、Reflection を活用して、C#でクラス名を取得する方法を具体的なコードとともにわかりやすく解説します。
C#でクラス名を取得する基本:GetType()の使い方
C#で最も基本的にクラス名を取得する方法は、オブジェクトの GetType() メソッドを使うことです。
class Person
{
}
class Program
{
    static void Main()
    {
        Person person = new Person();
        Console.WriteLine(person.GetType().Name);  // 出力: Person
    }
}
解説
- person.GetType()で- Typeオブジェクトを取得します。
- .Nameプロパティでクラス名(- Person)だけを取得できます。
他にも以下のような情報が取得できます。
Type type = person.GetType();
Console.WriteLine(type.FullName);     // 名前空間を含めた完全修飾名
Console.WriteLine(type.Namespace);    // 名前空間のみ
Console.WriteLine(type.Assembly);     // 所属アセンブリ
静的な型情報を取得するtypeofの使い方
オブジェクトのインスタンスではなく、型から直接クラス名を取得したい場合には typeof 演算子を使います。
Type type = typeof(Person);
Console.WriteLine(type.Name);       // 出力: Person
Console.WriteLine(type.FullName);   // 出力: [名前空間].Person
用途の例
- 属性によるクラス情報の読み取り
- 特定の型に対する共通処理の実装
- ジェネリクスや DI コンテナなど、型情報をキーとする場合
名前空間付きのクラス名を取得する
単にクラス名だけでなく、**完全修飾名(名前空間付き)**を取得したい場合は、FullName プロパティを使います。
Console.WriteLine(person.GetType().FullName);
// 例: MyApp.Models.Person
これはログ出力や例外のトラッキングなどで、クラスの出所を正確に示したい時に便利です。
Reflectionでアセンブリ内のクラス一覧を取得する
少し応用として、アセンブリに含まれるすべてのクラスの名前を一覧で取得する方法を紹介します。
using System;
using System.Reflection;
class Program
{
    static void Main()
    {
        Assembly assembly = Assembly.GetExecutingAssembly();
        foreach (Type type in assembly.GetTypes())
        {
            if (type.IsClass)
            {
                Console.WriteLine(type.FullName);
            }
        }
    }
}
解説
- Assembly.GetExecutingAssembly()で現在のアセンブリを取得。
- GetTypes()で全型一覧を取得。
- IsClassプロパティでクラスのみを抽出。
基底クラスやインターフェースの名前を取得する
クラス名だけでなく、そのクラスが継承している基底クラスや実装しているインターフェースの情報も取得できます。
Type type = typeof(System.IO.FileStream);
// 基底クラス
Console.WriteLine("BaseType: " + type.BaseType?.Name);
// インターフェース一覧
foreach (Type interfaceType in type.GetInterfaces())
{
    Console.WriteLine("Interface: " + interfaceType.Name);
}
ジェネリッククラス名を取得する際の注意点
ジェネリック型の場合、型パラメータを含めて取得するには工夫が必要です。
class Sample<T> { }
class Program
{
    static void Main()
    {
        var obj = new Sample<int>();
        Type type = obj.GetType();
        Console.WriteLine(type.Name);        // 出力: Sample`1
        Console.WriteLine(type.FullName);    // 出力: 名前空間.Sample`1[[System.Int32, mscorlib]]
    }
}
- Sampleの後の- `1はジェネリックパラメータが1つであることを示します。
- 実用上は GenericTypeArgumentsやMakeGenericTypeを使って名前を整形することもできます。
クラス名をログに活用する例
開発中のデバッグやログの中で、クラス名を出力することで、どのクラスから出力されたかが明確になります。
public class Logger
{
    public static void Log(object sender, string message)
    {
        string className = sender.GetType().Name;
        Console.WriteLine($"[{className}] {message}");
    }
}
使用例:
class OrderService
{
    public void Process()
    {
        Logger.Log(this, "処理を開始します");
    }
}
出力例:
[OrderService] 処理を開始します
クラス名の取得をユーティリティ化する
共通処理としてユーティリティクラスを作成しておくと便利です。
public static class TypeHelper
{
    public static string GetClassName<T>()
    {
        return typeof(T).Name;
    }
    public static string GetClassName(object obj)
    {
        return obj.GetType().Name;
    }
}
使用例:
var className1 = TypeHelper.GetClassName(new Person());
var className2 = TypeHelper.GetClassName<Person>();
まとめ
C#でクラス名を取得する方法はいくつかありますが、場面によって使い分けることが重要です。
- インスタンスから取得 → GetType().Name
- 型から取得 → typeof(ClassName).Name
- フルネームが必要 → .FullName
- アセンブリから一覧取得 → Assembly.GetTypes()
- ログや汎用処理 → ユーティリティ化
クラス名の取得をマスターすることで、より動的で柔軟なコードを書くことができ、保守性や再利用性も向上します。ぜひ今回紹介した内容を活かして、実際の開発に役立ててください。

