객체가 인터페이스를 구현하는지 테스트


355

개체가 C #에서 지정된 인터페이스를 구현하는 경우 가장 간단한 테스트 방법은 무엇입니까? ( Java 에서이 질문 에 대한 답변 )

답변:


569
if (object is IBlah)

또는

IBlah myTest = originalObject as IBlah

if (myTest != null)

85
+1 두 번째 캐스트는 아마도 첫 번째 캐스트와 함께 나중에 캐스트해야하므로 두 개의 캐스트 ( "is"와 명시 적 캐스트)를 요구하기 때문에 더 좋습니다. 두 번째 방법을 사용하면 한 번만 캐스팅 할 수 있습니다.
— Andrew Hare

51
@ 앤드류 : +1; Julian M Bucknall 의 클래식 Double-Casting AntiPattern 블로그 게시물에 대한 링크 를 다시 한 번 살펴보십시오 .
— Jeroen Wiert Pluimers

1
최적화는 아마도 첫 번째 경우에 두 번 캐스팅하지 않았습니까?
— BuZz

1
@Joreen, 당신이 "as"가 리턴하려고하는 널을 보유하지 않기 때문에 "as"를 사용할 수없는 구조를 가지고 작업한다면 그 링크는 한 지점을 놓치게됩니다. int?와 같은 클래스?, 항상 참조 유형이므로 인터페이스 레벨에서만 작업하는 경우에는 문제가되지 않습니다.
— MikeT

46
C # 6.0 이후 :if (object is IBlah iblah) { iblah.SomeMethod(); }
— Knelis

224

컴파일 타임에 인터페이스 유형을 알고 테스트중인 유형의 인스턴스가있는 경우 isor as연산자를 사용하는 것이 올바른 방법입니다. 다른 사람이 언급하지 않은 것 Type.IsAssignableFrom:

if( typeof(IMyInterface).IsAssignableFrom(someOtherType) )
{
}

나는 이것이 반환 된 배열을 보는 것보다 훨씬 깔끔하고 GetInterfaces클래스 작업도 장점 이라고 생각합니다 .


형식이 IList의 인스턴스화를 구현하는지 확인하려고합니다. "typeof (IList <>). IsAssignableFrom (someType)"을 사용하고 있지만 작동하지 않습니다.
— KeyboardDrummer

3
다른 질문으로 이것을 묻는 것이 좋습니다. someType이 목록 요소의 유형 인 경우 typeof (IList <>). MakeGenericType (someType)이 필요할 수 있습니다. someType이 목록 유형 인 경우 Type.GetGenericArguments 및 Type.GetGenericTypeDefinition을 확인해야합니다.
— 앤드류 케난

플러그인 시스템에서 유형 검사에 이것을 사용합니다. 객체의 인스턴스가 아직없는 상황에서 사용할 수 있습니다. 그러나 내가하고있는 일에 따라이 스타일과 Robert의 스타일을 모두 사용하므로 두 가지 방식으로 투표했습니다.
— James

이것은 오래된 의견이지만 @Steenreem의 질문에 대답하려면을 사용 typeof(IList).IsAssignableFrom(someType)하지 않고을 사용 하십시오 <>.
— saluce

이 방법은도 변환 운영자와 협력하고 TypeConverters가 참여하는 경우
— 헤럴드 Coppoolse에게

22

예를 들어 :

if (obj is IMyInterface) {}

수업 :

typeof(MyClass).GetInterfaces()인터페이스 가 포함되어 있는지 확인하십시오 .


1
if (Array.IndexOf (typeof (MyClass) .GetInterfaces (), typeof (IMyInterface)))! = -1) {...}
— Constantin

2
또는 : if (typeof (MyClass) .GetInterfaces (). Contains (typeof (IMyInterface))) {...}
— 랜스 피셔


16

@AndrewKennan의 대답에 대한 변형은 최근 런타임에 얻은 유형에 대해 최근에 사용되었습니다.

if (serviceType.IsInstanceOfType(service))
{
    // 'service' does implement the 'serviceType' type
}

7

이 게시물 은 좋은 답변입니다.

public interface IMyInterface {}

public class MyType : IMyInterface {}

이것은 간단한 샘플입니다.

typeof(IMyInterface).IsAssignableFrom(typeof(MyType))

또는

typeof(MyType).GetInterfaces().Contains(typeof(IMyInterface))

3

"is"연산자를 사용하여 테스트하는 것 외에도 메소드를 장식하여 전달 된 변수가 다음과 같이 특정 인터페이스를 구현하는지 확인할 수 있습니다.

public static void BubbleSort<T>(ref IList<T> unsorted_list) where T : IComparable
{
     //Some bubbly sorting
}

이것이 어떤 .Net 버전으로 구현되었는지 잘 모르겠으므로 버전에서 작동하지 않을 수 있습니다.


2
.net 2.0에 제네릭이 추가되었습니다.
— Robert C. Barth

이 스레드에서 유일한 컴파일 타임 검사입니다. 감사합니다.
— 더스틴 말론

2

나를 위해 일한 것은 다음과 같습니다.

Assert.IsNotNull(typeof (YourClass).GetInterfaces().SingleOrDefault(i => i == typeof (ISomeInterface)));


1

최근 Andrew Kennan의 답변을 사용해 보았지만 어떤 이유로 든 작동하지 않았습니다. 대신 이것을 사용하고 작동했습니다 (참고 : 네임 스페이스를 작성해야 할 수도 있습니다).

if (typeof(someObject).GetInterface("MyNamespace.IMyInterface") != null)

2
이 경로로 이동하면 마술 문자열의 팬이 아니므로 최소한 "MyNamespace.IMyInterface"대신 typeof (IMyInterface) .Name으로 변경해야합니다. 리팩토링 증거를 보너스로 지정하는 데 도움이됩니다.
— greyalien007

0

나는 사용했다

Assert.IsTrue(myObject is ImyInterface);

myObject가 내 인터페이스 ImyInterface를 구현 한 객체인지 테스트하는 단위 테스트 테스트.


-1

변수를 메소드에 전달하고 인터페이스 또는 객체인지 확실하지 않은 상황이있었습니다.

목표는 다음과 같습니다.

  1. item이 인터페이스 인 경우 인터페이스를 생성자 호출에서 매개 변수로 사용하여 해당 인터페이스를 기반으로 오브젝트를 인스턴스화하십시오.
  2. 항목이 객체 인 경우 호출의 구성자가 인터페이스를 기대하고 코드를 탱크로 만들고 싶지 않기 때문에 null을 반환합니다.

나는 이것을 다음과 같이 달성했다.

    if(!typeof(T).IsClass)
    {
       // If your constructor needs arguments...
       object[] args = new object[] { my_constructor_param };
       return (T)Activator.CreateInstance(typeof(T), args, null);
    }
    else
       return default(T);

-12

이것은 작동해야합니다 :

MyInstace.GetType().GetInterfaces();

그러나 너무 좋은 :

if (obj is IMyInterface)

또는 심지어 (아주 우아하지 않음) :

if (obj.GetType() == typeof(IMyInterface))

9
typeof (IMyInterface)와 같은지 확인하는 것은 항상 실패합니다. 공감.
— Jay Bazuzi 님의

권리. 인터페이스 인스턴스가 없습니다.
— Rauhotz
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.