'T'가 클래스 / 인터페이스를 상속하거나 구현하는지 확인


92

T가 클래스 / 인터페이스를 상속 / 구현하는지 테스트하는 방법이 있습니까?

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

4
이것은 작동하는 것처럼 보입니다 ... if (typeof (TestClass) .IsAssignableFrom (typeof (T))), 누군가 내 의심을 확인할 수 있습니까? 감사!
user1229895

나는이 답변이 여러 번 중복된다는 것을 절대적으로 확신합니다!
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))
Dr. Andrew Burnett-Thompson

완료되지 않은 nikeee; 오래된 대답은 여전히 ​​있습니다. :) 나는 무엇이 잘못되었는지 알아 내기 위해 몇 초를 걸었다. 어쨌든 +1, .net 프레임 워크의 멋진 기능입니다.
Samuel

사실, 당신이 언급 한 방식은 제가 얼마 전에 사용했던 방식입니다. 나는 이것을 고쳤다. 이전 의견을 참조하십시오. T inherits U실제로 typeof(T).IsAssignableFrom(typeof(U)).
nikeee

2
이것이 거의 작동하지만 if T가 다른 유형으로 제한되고 TOther실행될 때 실제로 전달 된 유형 이 아니라 typeof(T)실제로 평가 typeof(TOther)되며이 T경우 typeof(SomeInterface).IsAssignableFrom(typeof(T))실패하는 문제가 있습니다 ( TOther구현하지 않는다고 가정 SomeInterface). 구체적인 유형이 SomeInterface.
Dave Cousineau 2016 년

1
.NET의 핵심에서 IsAssignableFromTypeInfo: 샘플은 다음과해야하므로 클래스 만, 그것의 유일한 인수로 소속 카테고리를 허용typeof(Employee).GetTypeInfo().IsAssignableFrom(typeof(T).GetTypeInfo())
로 카


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, 또는 현재는 경우 Typeinterface것을 c구현하는 경우, 또는 c제네릭 형식 매개 변수이며, 전류 Type의 제약 중 하나를 나타냅니다 c, 또는 만약이 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. T그리고 Employee같은 종류의 표현; 또는,
  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를 통해 HorizontalRunDump)

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;
}

결과

baseclass-> baseclass

진실

child1-> baseclass

그릇된

baseclass-> child1

진실

child2-> baseclass

그릇된

baseclass-> child2

진실

nobase-> baseclass

그릇된

baseclass-> nobase

그릇된

  • 실패 : c1 = b1
  • b1 = c1
  • 실패 : c2 = b1
  • b1 = c2

2

구문은 다음과 같습니다. typeof(Employee).IsAssignableFrom(typeof(T));


이것은 의도 된 구문입니다. +1
Luke 14

0

IsAssignableFrom이 다른 사람들이 말한 것처럼 가장 좋은 방법이지만 클래스가 다른 클래스에서 상속되는지 확인하기 만하면되는 경우 typeof(T).BaseType == typeof(SomeClass)에도 작업을 수행합니다.


SomeClass에서 직접 파생되지 않는 한 작동합니다 BaseClass.
Suncat2000

0

객체 o가 클래스를 상속 하는지 또는 인터페이스를 구현 하는지 알 수있는 또 다른 방법 은 isas연산자 를 사용하는 것 입니다.

객체가 클래스를 상속하는지 또는 인터페이스를 구현하는지 만 알고 싶다면 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.