유형이 하위 유형인지 또는 객체 유형인지 어떻게 확인합니까?


335

C #에서 형식이 다른 형식의 하위 클래스인지 확인하려면 쉽습니다.

typeof (SubClass).IsSubclassOf(typeof (BaseClass)); // returns true

그러나 이것은 실패합니다.

typeof (BaseClass).IsSubclassOf(typeof (BaseClass)); // returns false

OR연산자 를 사용하지 않거나 확장 메서드를 사용 하지 않고 형식이 기본 클래스 자체의 하위 클래스인지 아니면 하위 클래스인지 확인할 수있는 방법이 있습니까?

답변:


499

분명히 요

옵션은 다음과 같습니다.

Type.IsSubclassOf

이미 알고 있듯이 두 유형이 동일한 경우 작동하지 않습니다. 다음은 샘플 LINQPad 프로그램입니다.

void Main()
{
    typeof(Derived).IsSubclassOf(typeof(Base)).Dump();
    typeof(Base).IsSubclassOf(typeof(Base)).Dump();
}

public class Base { }
public class Derived : Base { }

산출:

True
False

이는 Derived의 서브 클래스 Base이지만 Base(자명하게) 자체의 서브 클래스가 아님을 나타냅니다 .

Type.IsAssignableFrom

자, 이것은 당신의 특정한 질문에 대답 할 것이지만, 그것은 또한 당신에게 잘못된 긍정을 줄 것입니다. Eric Lippert가 의견에서 지적했듯이,이 방법은 실제로 True위의 두 가지 질문에 True대해 반환 하지만, 이것에 대해서는 반환 하지 않을 것입니다.

void Main()
{
    typeof(Base).IsAssignableFrom(typeof(Derived)).Dump();
    typeof(Base).IsAssignableFrom(typeof(Base)).Dump();
    typeof(int[]).IsAssignableFrom(typeof(uint[])).Dump();
}

public class Base { }
public class Derived : Base { }

다음과 같은 결과가 나옵니다.

True
True
True

마지막으로 True메소드 가 요청한 질문 에만 응답 한 경우 uint[]상속 된 int[]유형이거나 동일한 유형 임을 나타내며, 그렇지 않습니다.

따라서 IsAssignableFrom완전히 정확하지도 않습니다.

isas

귀하의 질문 is과 관련 as하여 "문제" 는 객체에서 작업하고 유형 중 하나를 코드로 직접 작성해야하지만 객체에서는 작동하지 않아야한다는 것입니다 Type.

다시 말해, 이것은 컴파일되지 않습니다 :

SubClass is BaseClass
^--+---^
   |
   +-- need object reference here

이것도 아닙니다 :

typeof(SubClass) is typeof(BaseClass)
                    ^-------+-------^
                            |
                            +-- need type name here, not Type object

이것도 아닙니다 :

typeof(SubClass) is BaseClass
^------+-------^
       |
       +-- this returns a Type object, And "System.Type" does not
           inherit from BaseClass

결론

위의 방법이 귀하의 요구에 맞을 수도 있지만 질문에 대한 유일한 정답은 추가 확인이 필요하다는 것입니다.

typeof(Derived).IsSubclassOf(typeof(Base)) || typeof(Derived) == typeof(Base);

물론 방법에서 더 의미가 있습니다.

public bool IsSameOrSubclass(Type potentialBase, Type potentialDescendant)
{
    return potentialDescendant.IsSubclassOf(potentialBase)
           || potentialDescendant == potentialBase;
}

2
감사! 확인을 취소하고 MSDN 설명서에 대한 링크를 제공해야한다고 언급 했으므로 올바른 답변으로 표시합니다 (8 분 더 기다려야 함).
Daniel T.

71
이것은 실제로 질문이 요구하는 것을 수행하지는 않습니다. 이것은 한 유형이 다른 유형의 서브 클래스인지 여부를 판별하는 것이 아니라 한 유형이 다른 유형과 지정 가능한지 여부를 판별합니다. uint 배열은 int 배열의 서브 클래스가 아니지만 할당 호환 가능합니다. IEnumerable <Giraffe>는 IEnumerable <Animal>의 하위 클래스는 아니지만 v4에서 할당 호환 가능합니다.
Eric Lippert

Java와 같은 메소드 이름 에서이 작업을 수행 할 수있는 방법이 없습니까? ```void <? Base> saveObject (? objectToSave)`를 확장합니다.
Oliver Dixon

2
이것에 어떻게 IsInstanceOfType맞을까요?
Lennart

IsSameOrSubclass를 확장 메소드로 변환하고 싶은 유혹이있을 수 있지만,이를 반대하는 것이 좋습니다. 읽고 쓰는 것이 약간 어색하고 엉망이되기 쉽습니다 (potentialBase와 potentialDescendant의 순서를 바꾸면 치명적일 수 있습니다).
jrh



1

Xamarin Forms PCL 프로젝트에서 수행하려는 경우 위의 솔루션을 사용 IsAssignableFrom하면 오류가 발생합니다.

오류 : 'Type'에 'IsAssignableFrom'에 대한 정의가 포함되어 있지 않으며 'Type'유형의 첫 번째 인수를 허용하는 확장 메소드 'IsAssignableFrom'을 찾을 수 없습니다 (사용 지시문 또는 어셈블리 참조가 누락 되었습니까?)

물체를 IsAssignableFrom요구하기 때문 TypeInfo입니다. 다음 GetTypeInfo()방법을 사용할 수 있습니다 System.Reflection.

typeof(BaseClass).GetTypeInfo().IsAssignableFrom(typeof(unknownType).GetTypeInfo())


0

나는 누군가가 나에게 공유하고 그것이 왜 나쁜 생각인지 공유하기를 희망 하여이 답변을 게시하고 있습니다. 내 응용 프로그램에서 Type 속성이 typeof (A) 또는 typeof (B)인지 확인하고 싶습니다. 여기서 B는 A에서 파생 된 클래스입니다. 따라서 내 코드 :

public class A
{
}

public class B : A
{
}

public class MyClass
{
    private Type _helperType;
    public Type HelperType
    {
        get { return _helperType; }
        set 
        {
            var testInstance = (A)Activator.CreateInstance(value);
            if (testInstance==null)
                throw new InvalidCastException("HelperType must be derived from A");
            _helperType = value;
        }
    }
}

나는 여기에 약간 순진한 것처럼 느껴지므로 피드백을 환영합니다.


2
이 아이디어에는 몇 가지 문제가 있습니다. 1) 형식에 매개 변수가없는 생성자가 필요하거나 CreateInstance가 실패합니다. 2) (A)로 캐스팅하면 캐스팅을 할 수 없으면 null을 반환하지 않습니다. 3) 실제로 새 인스턴스가 필요하지 않으므로 쓸모없는 할당이 있습니다. 받아 들여진 대답이 더 좋습니다 (완벽하지는 않지만).
Marcel Popescu

피드백 감사드립니다. 매우 도움이됩니다.
baskren

@baskren, 아마도 그의 유용한 의견을 찬성했습니다. 나는 # 1을 찬성했다.
Developer63
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.