[C#] ある型が指定したクラスまたはインターフェイスにキャスト可能か判定する方法

2024-04-22 (月)

通常は is や as でキャストできるか判定しますが、Type 指定でクラスやインターフェイスにキャスト可能か判定する方法です。
is と同じ結果になる方法だと思います。指定したクラスの派生または、指定したインターフェイスを実装しているか判定できます。

環境

  • .NET 8.0.4 (SDK 8.0.204)
  • C# 12.0
  • Visual Studio 2022 Version 17.9.6
  • Windows 11 Pro 22H2 22631.3447

結果

// このようなクラスがあるとします
interface IExample;
class BaseClass : IExample;
class DerivedClass : BaseClass;

void Main()
{
    // 変数定義
    var base1 = new BaseClass();
    var derived1 = new DerivedClass();

    // 変数から判定する場合は IsInstanceOfType() を使用します
    // derived is BaseClass 相当
    typeof(BaseClass).IsInstanceOfType(base1);     // true
    typeof(BaseClass).IsInstanceOfType(derived1);  // true
    typeof(IExample).IsInstanceOfType(derived1);   // true

    // Type から判定する場合は、IsAssignableFrom() を使用します
    // derived is BaseClass 相当
    typeof(BaseClass).IsAssignableFrom(typeof(BaseClass));     // true
    typeof(BaseClass).IsAssignableFrom(typeof(DerivedClass));  // true
    typeof(IExample).IsAssignableFrom(typeof(DerivedClass));   // true

    // IsAssignableTo() は IsAssignableFrom() の引数指定が逆になります
    // derived is BaseClass 相当
    typeof(BaseClass).IsAssignableTo(typeof(BaseClass));     // true
    typeof(DerivedClass).IsAssignableTo(typeof(BaseClass));  // true
    typeof(DerivedClass).IsAssignableTo(typeof(IExample));   // true
}

ジェネリック型は、型引数も一致している場合に true です。オープン ジェネリック型同士も true です。

// List<> is List<> 相当
typeof(List<>).IsAssignableTo(typeof(List<>));       // true
typeof(List<>).IsAssignableTo(typeof(List<int>));    // false

// List<int> is List<int> 相当
typeof(List<int>).IsAssignableTo(typeof(List<int>)); // true
typeof(List<int>).IsAssignableTo(typeof(List<>));    // false

説明

以下のメソッドを使用しています。

これらの結果は、全て同じと思われます。

  • 引数に null を指定すると false が返ります。
    • is 演算子と同じです。
  • 内部的に Type.IsAssignableFrom(Type?) が使用されます。
// https://github.com/dotnet/runtime/blob/v8.0.3/src/libraries/System.Private.CoreLib/src/System/Type.cs#L562
public virtual bool IsInstanceOfType([NotNullWhen(true)] object? o) => o == null ? false : IsAssignableFrom(o.GetType());

// https://github.com/dotnet/runtime/blob/v8.0.3/src/libraries/System.Private.CoreLib/src/System/Type.cs#L121-L122
public bool IsAssignableTo([NotNullWhen(true)] Type? targetType) => targetType?.IsAssignableFrom(this) ?? false;

感謝

2024-04-22 (月)