[C#] BがAを継承しているのか(型変換が可能か)を判定する
is
を用いる
型のテスト演算子var b = new B();
var bIsA = b is A;
if (bIsA) {
// 変数bはAから継承した
// 変数bはインターフェースAを持つ
// 変数bはAへの暗黙的な参照変換を持つ
// 変数bはnullではない
}
is
演算子は左辺が右辺との間に互換性があるかを調べます。調べた結果は真偽値(bool
)で返却されます。互換性がある場合はtrue
です。
`if(b is A a)` という書き方
C#7.0以降、is
演算子は宣言パターンに対して照合できます。宣言パターンを使用すると、今まで変数を宣言してキャスト、またはas
演算子を用いてnullチェックを行う、といった書き方とは別の書き方ができます。
var b = new B();
if (b is A a) {
// if文内で変数aが、クラスまたはインターフェースAとして振舞う
a.RunOnlyA();
} else {
// if文内で変数aが、クラスまたはインターフェースAとして振舞えない
}
var b = new B();
if (!(b is A a)) {
// if文内で変数aが、クラスまたはインターフェースAとして振舞えない
} else {
a.RunOnlyA();
}
System.Type
クラスの関数を使う
`System.Type.IsSubclassOf`を用いる
System.Type aType = typeof(A);
System.Type bType = typeof(B);
if (bType.IsSubclassOf(aType)) {
// タイプbはAから継承した
}
System.Type.IsSubclassOf
は System.Type
を引数に持つ関数です。
引数で渡されたタイプが継承元であるかを返却します。
インターフェースを実装しているのかは判断できません。
`System.Type.IsAssignableTo`を用いる
System.Type aType = typeof(A);
System.Type bType = typeof(B);
if (bType.IsAssignableTo(aType)) {
// タイプBはAから継承した (あるいは間接的に継承した)
// タイプBはAというインターフェースを実装している
System.Console.Write("{0} is assignable to {1}", bType, aType);
}
System.Type.IsAssignableTo
は、引数で渡された型 に 代入可能かを真偽値で返却します。
そのため、継承元や間接的に継承しているクラスや、インターフェースであっても代入可能であればtrue
を返却します。
`System.Type.IsAssignableFrom` を用いる
System.Type aType = typeof(AClass);
System.Type bType = typeof(BClass);
if (aType.IsAssignableFrom(bType)) {
// タイプBはAから継承した (あるいは間接的に継承した)
// タイプBはAというインターフェースを実装している
}
System.Type.IsAssignableFrom
は、丁度 System.Type.IsAssignableTo
と逆の動きをします。つまり引数に渡された型 が 代入可能かを真偽値で返却します。
`System.Type.IsInstanceOfType` を用いる
var b = new BClass();
System.Type aType = typeof(AClass);
if (aType.IsInstanceOfType(b)) {
// 変数bはAから継承した (あるいは間接的に継承した)
// 変数bはAというインターフェースを実装している
// 変数bがnullである
}
System.Type.IsInstanceOfType
は引数で渡された変数 b
が継承可能であったり、インターフェースが実装されている場合にtrueを返却します。
説明
C#では、型変換したい変数が、指定された型に型変換できなかった場合の対策として is
演算子を用いることができます。
if
文と組み合わせることによって、変換できた場合と変換できなかった場合という書き方ができます。
一方で、System.Type
には引数で渡された型(または変数)がどういう継承関係にあるのか、(あるいはインターフェースが実装されたのか)を判定する方法があります。
System.Type
だけを扱いたい場合はこちらの方法を使います。
多くの場合 `is` 演算子の判定で十分です
is
演算子出の書き方と、System.Type.IsInstanceOfType
での書き方を比較すると、
is
演算子のほうが英語の文章に近い書き方なので、読みやすいです。
var b = new B();
if (b is A) {
// ...
}
var b = new B();
if (typeof(A).IsInstanceOfType(b)) {
// ...
}
参考
- 型のテスト演算子とキャスト式 - C# リファレンス | Microsoft Docs
- パターン - C# リファレンス | Microsoft Docs
- T型が任意のクラスを継承しているか判定するには? - teratail
- Type.IsSubclassOf(Type) Method (System) | Microsoft Docs
- Type.IsAssignableTo(Type) メソッド (System) | Microsoft Docs
- Type.IsAssignableFrom(Type) メソッド (System) | Microsoft Docs
- Type.IsInstanceOfType(Object) メソッド (System) | Microsoft Docs
Discussion