「T」がクラス/インターフェースを継承または実装しているかどうかを確認する


92

Tがクラス/インターフェースを継承/実装しているかどうかをテストする方法はありますか?

private void MyGenericClass<T> ()
{
    if(T ... inherits or implements some class/interface
}

4
これは動作するようです... if(typeof(TestClass).IsAssignableFrom(typeof(T)))、誰かが私の疑いを確認できますか?ありがとう!
user1229895 2012年

私はこの答えが何度も繰り返されると確信しています!
Felix K.

3
Felix Kこの回答が何度も繰り返されたとしても、それは多くの人の役に立ちます;)... 5分前の私のように:)
Samuel

回答:


136

Type.IsAssignableFrom()というメソッドがあります。

T継承/実装するかどうかを確認するにはEmployee

typeof(Employee).IsAssignableFrom(typeof(T));

.NET Coreをターゲットにしている場合、メソッドはTypeInfoに移動しました。

typeof(Employee).GetTypeInfo().IsAssignableFrom(typeof(T).Ge‌​tTypeInfo())

例はtypeof(T).IsAssignableFrom(typeof(IMyInterface))で答えを更新する必要があります
アンドリューバーネットトンプソン博士

まだナイキじゃない。古い答えはまだそこにあります。:)私は何が悪いのかを理解するのに数秒かかりました。とにかく、+ 1、.netフレームワークの素晴らしい機能です。
Samuel

実際、あなたが言及する方法は、私が少し前にそれを持っていた方法です。これを修正しました。以前のコメントを参照してください。T inherits U実際にはに変換されtypeof(T).IsAssignableFrom(typeof(U))ます。
nikeee 2014年

2
これはほとんど機能しますが、if Tが他の型に制約されているTOther場合、実行typeof(T)するtypeof(TOther)T、実際に渡された型ではなく、実際に評価され、その場合typeof(SomeInterface).IsAssignableFrom(typeof(T))は失敗します(TOtherも実装していないと想定SomeInterface)。あなたの具象型は実装しましたがSomeInterface
Dave Cousineau

1
.NETコアでIsAssignableFromTypeInfo:サンプルは以下でなければなりませんので、それは、唯一の引数だとしてクラスのみのTypeInfoを受け入れるtypeof(Employee).GetTypeInfo().IsAssignableFrom(typeof(T).GetTypeInfo())
へのKa


16

コンパイル中に確認したい場合:エラーが必要なインターフェース/クラスを実装してT いない場合、次の制約を使用できます

public void MyRestrictedMethod<T>() where T : MyInterface1, MyInterface2, MySuperClass
{
    //Code of my method here, clean without any check for type constraints.
}

お役に立てば幸いです。


12

正しい構文は

typeof(Employee).IsAssignableFrom(typeof(T))

ドキュメンテーション

戻り値: trueもしc、電流がType同じタイプを表し、又は電流が場合Typeの継承階層にあるc、または現在は次の場合Typeであるinterfaceことc実装、または場合は、cジェネリック型パラメータであり、電流Typeの制約の1つを表しc、またはif cは値のタイプをType表し、現在の値はNullable<c>Nullable(Of c)Visual Basicでは)を表します。falseこれらの条件のいずれもない場合true、または場合がcありますnull

ソース

説明

もしEmployee IsAssignableFrom T、その後Tから継承Employee

使い方

typeof(T).IsAssignableFrom(typeof(Employee)) 

どちらかが戻ったときにtrue のみ戻ります

  1. TEmployee同じタイプを表す; または、
  2. Employeeから継承しTます。

これは、での使用を意図することができるいくつかのときを決定するために、ケースが、元の質問(およびより一般的な使用法)のためにT継承または器具いくつかclass/ interface使用。

typeof(Employee).IsAssignableFrom(typeof(T))

9

誰もが本当に意味することは:

typeof(BaseType).IsAssignableFrom(typeof(DerivedType)) // => true

あなたは、文字通りすることができますので、から割り当てるのインスタンスDerivedTypeのインスタンスにBaseType

DerivedType childInstance = new DerivedType();
BaseType parentInstance = childInstance; // okay, assigning base from derived
childInstance = (DerivedType) parentInstance; // not okay, assigning derived from base

いつ

public class BaseType {}
public class DerivedType : BaseType {}

そして、あなたの頭を包むのに問題がある場合のいくつかの具体的な例:

(LinqPadを使用するため、HorizontalRunおよびDump

void Main()
{
    // http://stackoverflow.com/questions/10718364/check-if-t-inherits-or-implements-a-class-interface

    var b1 = new BaseClass1();

    var c1 = new ChildClass1();
    var c2 = new ChildClass2();
    var nb = new nobase();

    Util.HorizontalRun(
        "baseclass->baseclass,child1->baseclass,baseclass->child1,child2->baseclass,baseclass->child2,nobase->baseclass,baseclass->nobase",
        b1.IsAssignableFrom(typeof(BaseClass1)),
        c1.IsAssignableFrom(typeof(BaseClass1)),
        b1.IsAssignableFrom(typeof(ChildClass1)),
        c2.IsAssignableFrom(typeof(BaseClass1)),
        b1.IsAssignableFrom(typeof(ChildClass2)),
        nb.IsAssignableFrom(typeof(BaseClass1)),
        b1.IsAssignableFrom(typeof(nobase))
        ).Dump("Results");

    var results = new List<string>();
    string test;

    test = "c1 = b1";
    try {
        c1 = (ChildClass1) b1;
        results.Add(test);
    } catch { results.Add("FAIL: " + test); }

    test = "b1 = c1";
    try {
        b1 = c1;
        results.Add(test);
    } catch { results.Add("FAIL: " + test); }

    test = "c2 = b1";
    try {
        c2 = (ChildClass2) b1;
        results.Add(test);
    } catch { results.Add("FAIL: " + test); }

    test = "b1 = c2";
    try {
        b1 = c2;
        results.Add(test);
    } catch { results.Add("FAIL: " + test); }

    results.Dump();
}

// Define other methods and classes here
public static class exts {
    public static bool IsAssignableFrom<T>(this T entity, Type baseType) {
        return typeof(T).IsAssignableFrom(baseType);
    }
}


class BaseClass1 {
    public int id;
}

class ChildClass1 : BaseClass1 {
    public string name;
}

class ChildClass2 : ChildClass1 {
    public string descr;
}

class nobase {
    public int id;
    public string name;
    public string descr;
}

結果

ベースクラス->ベースクラス

本当

child1->ベースクラス

誤り

baseclass-> child1

本当

child2->ベースクラス

誤り

baseclass-> child2

本当

nobase-> baseclass

誤り

baseclass-> nobase

誤り

そして

  • 失敗:c1 = b1
  • b1 = c1
  • 失敗:c2 = b1
  • b1 = c2


0

他の人が述べたように、IsAssignableFromが最善の方法ですが、クラスが別のクラスから継承するかどうかを確認するだけでよい場合typeof(T).BaseType == typeof(SomeClass)は、その仕事も行います。


SomeClassから直接派生しない限り、これは機能しBaseClassます。
Suncat2000

0

オブジェクトoがクラスを継承しているか、インターフェースを実装しているかを確認する別の方法は、isand as演算子を使用することです。

オブジェクトがクラスを継承しているか、インターフェースを実装しているかだけを知りたい場合、is演算子はブール結果を返します。

bool isCompatibleType = (o is BaseType || o is IInterface);

テスト後に継承されたクラスまたは実装されたインターフェイスを使用する場合、asオペレーターは安全なキャストを実行し、互換性がある場合は継承されたクラスまたは実装されたインターフェイスへの参照を返し、互換性がない場合はnullを返します。

BaseType b = o as BaseType; // Null if d does not inherit from BaseType.

IInterface i = o as IInterface; // Null if d does not implement IInterface.

タイプしかない場合はT、@ nikeeeの回答を使用してください。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.