유형 검사: typeof, GetType 또는 is?

많은 사람들이 다음 코드를 사용하는 것을 보았습니다:

Type t = typeof(obj1);
if (t == typeof(int))
    // Some code here

하지만 여러분도 이렇게 할 수 있다는 것을 알고 있습니다:

if (obj1.GetType() == typeof(int))
    // Some code here

또는 이렇게 하세요:

if (obj1 is int)
    // Some code here

개인적으로는 마지막이 가장 깔끔하다고 생각하는데 제가 놓친 부분이 있나요? 어느 것이 가장 좋은가요, 아니면 개인적인 취향인가요?

질문에 대한 의견 (6)
해결책

모두 다르다.

  • '유형' 는 메리 페로프 이름 (컴파일 타임에 지정할 수 있습니다). '-' 게티페 런타임용으로 개발하십시오 유형의 인스턴스를 된다.
  • '는' 가 되면 상속 진단트리 인스턴스를 반환합니다.

&lt h3&gt Example&lt /h3>;;;

class Animal { } 
class Dog : Animal { }

void PrintTypes(Animal a) { 
    Console.WriteLine(a.GetType() == typeof(Animal)); // false 
    Console.WriteLine(a is Animal);                   // true 
    Console.WriteLine(a.GetType() == typeof(Dog));    // true
    Console.WriteLine(a is Dog);                      // true 
}

Dog spot = new Dog(); 
PrintTypes(spot);

&lt hr>;

&gt. (T) '' 메리 페로프 어때? 또한 해결되었으므로 는 컴파일 타임에?

예. T 는 항상 어떤 유형의 표현식에서는 있다. 단, 기본적으로 일반 방법은 여러 가지 방법을 통해 적절한 유형을 것과 마찬가지입니다. 예:

string Foo(T parameter) { return typeof(T).Name; }

Animal probably_a_dog = new Dog();
Dog    definitely_a_dog = new Dog();

Foo(probably_a_dog); // this calls Foo and returns "Animal"
Foo(probably_a_dog); // this is exactly the same as above
Foo(probably_a_dog); // !!! This will not compile. The parameter expects a Dog, you cannot pass in an Animal.

Foo(definitely_a_dog); // this calls Foo and returns "Dog"
Foo(definitely_a_dog); // this is exactly the same as above.
Foo(definitely_a_dog); // this calls Foo and returns "Animal". 
Foo((Animal)definitely_a_dog); // this does the same as above, returns "Animal"
해설 (9)

컴파일 시에 타입을 가져오려면 typeof를 사용합니다. 실행 시 실행 시*에 타입을 가져오고 싶을 때는 GetType을 사용합니다. is`는 형변환을 수행하므로 사용할 경우가 거의 없으며, 대부분의 경우 결국 변수를 형변환하게 됩니다.

여러분이 고려하지 않은 네 번째 옵션이 있습니다(특히 찾은 유형으로 객체를 캐스팅하려는 경우); 그것은 as를 사용하는 것입니다.

Foo foo = obj as Foo;

if (foo != null)
    // your code here

이 방법은 하나의 형변환만 사용하는 반면 이 방법은 하나의 형변환만 사용합니다:

if (obj is Foo)
    Foo foo = (Foo)obj;

이 필요합니다.

해설 (6)

1.

Type t = typeof(obj1);
if (t == typeof(int))

이건 불법 메리 페로프 때문에 때만 아닌 추상형데이터타입 대한 변수에 의존한다. 내가 solaris. obj1 은 변수. 그래서, 이런 식으로 메리 페로프 는 컴파일 타임에 업무를 대신 정적 및 높여줍니까 런타임용으로 개발하십시오.

2.

if (obj1.GetType() == typeof(int))

이 경우 int, int 유형의 obj1 것은 확실히 obj1 될 경우 if 에서 파생시킵니다 찼음을 거짓값.

3.

if (obj1 is int)

이것은 int, int 의 경우, 아니면 진정한 obj1 백업이었습니다 파생시킵니다 클래스 불렀으매 구축, 아니면 인터페이스입니다 호출됨 int.

해설 (5)
Type t = typeof(obj1);
if (t == typeof(int))
    // Some code here

이것은 오류가 발생했습니다. C # 에서 수행되는 연산자입니다 수만 시행하십시오 유형 이름, 객체가 아닌.

if (obj1.GetType() == typeof(int))
    // Some code here

이렇게 하면 원하는 대로 일을 않을 수도 있을 것으로 기대하고 있다. # 39 로, ve, it& you& 값에 대한 유형, 이 슬라이드에서는 # 39 에 사용할 수 있으나,) 는 동일한 문자 참조 유형을 것이다 유형, 안 되면 무언가 복귀하십시오 상속 계층 구조에서. 예를 들면 다음과 같습니다.

class Animal{}
class Dog : Animal{}

static void Foo(){
    object o = new Dog();

    if(o.GetType() == typeof(Animal))
        Console.WriteLine("o is an animal");
    Console.WriteLine("o is something else");
}

이는 ',', 'o 는 인쇄하십시오 &quot 뭔가 else&quot 때문에' 동물 'o' 는 '개이라 아닌 유형의'. 그러나 이 작품을 만들 수 있습니다 '방법' 을 사용할 경우 이사시냐블레프롬 '유형' 클래스.

if(typeof(Animal).IsAssignableFrom(o.GetType())) // note use of tested type
    Console.WriteLine("o is an animal");

이 기법은 찻입 여전히 심각한 문제가 될 수 있지만. 이 경우, a call to throw 게티페 () '은' nulll 가변입니다 누얼레페렌스엑스티온. 그래서 이를 제대로 작동하려면 you& # 39; d do.

if(o != null && typeof(Animal).IsAssignableFrom(o.GetType()))
    Console.WriteLine("o is an animal");

이와 함께 '는' 키워드 중 avamer 비헤이비어를 있습니다. 따라서, 이 경우, 이는 '는' 키워드를 비헤이비어를 운영까지도 콩지름에 가독성을 높이고 보다 더 효율적이다.

if(o is Animal)
    Console.WriteLine("o is an animal");

하지만, 대부분의 경우 '는' 키워드 그래도말야 isn& # 39, t, s # 39 it& 너희는너희가 진정으로 원하는 만큼 알고 있기 때문에, 보통 그냥 객체가 특정 유형의. 일반적으로, 실제로 사용할 수 있는 운영까지도 로케이터로 인스턴스입니다 해당 유형에 필요한 캐스팅 너무. 그래서 다음과 같은 코드를 먹어서나 교도관님도요 찾아볼 수 있습니다.

if(o is Animal)
    ((Animal)o).Speak();

그러나 CLR object& 확인 할 수 있는 # 39 의 유형을 최대 2 배. 또 한 번 확인할 수 있는 'o' 는 '는' 연산자입니다 만족시킬 경우, 그 '동물', 다시 검증하십시오 확인란 거냐 "라고 언급했다.

39 의 it& 이를 효율적으로 사용하십시오.

Animal a = o as Animal;
if(a != null)
    a.Speak();

39 는 '이' 으로 연산자입니다 won& 캐스트, 그 대신 'null' 실패하면 다시 예외가 아니다. 이런 식으로 CLR 의 유형, 그리고 그 이후로, # 39 는 object& 딱 한 번 누르기만 하면 널 확인 할 수 있는 것이 더 효율적입니다.

하지만 주의해야 합니다. 많은 사람들이 함께 트랩할 빠지는 '도'. # 39 doesn& 때문에, t, 일부 사람들이 아니라, safe&quot &quot 예외가 발생합니다. 이를 사용하여, 캐스팅, 그들은 단독으로 기피 일반 방송. 이로 인해 오류뿐만 다음과 같습니다.

(o as Animal).Speak();

이 경우 회사는 확실히요 'o' 가 될 것으로 보고 항상 '동물', 그리고 그들의 가정 정확한지 deltamove 설명하였노라 작동합니다. 그들이 잘못된 종료 후, re 신앙이니라 they& # 39 이것은 누얼레페렌스엑스티온 '가'. 함께 한 '대신' 일반 캐스트 (cast), 그들은 틀림없이 이 문제를 제대로 된 베르발드카스티스세페시옹 식별됩니다 더 있을 것이라고 말했다.

가끔 이 버그는 찾기 힘들 수 있습니다.

class Foo{
    readonly Animal animal;

    public Foo(object o){
        animal = o as Animal;
    }

    public void Interact(){
        animal.Speak();
    }
}

이것은 또 다른 개발자가 되기 위해 '동물' 는 'o' 확실히요 검색되어야 사례가 있지만, 이 때마다 isn& # 39 에 있는 '으로, t 명백하네 구성자를' 캐스트 사용됩니다. # 39 에 도달할 때까지 ',' s not 명백하네 it& 있는 '동물' 이 방법을 적극 상호 작용하는 것으로 필드는 배정됩니다. 이 경우 들어보겠소 아니라 끝날 때까지 함께 잘못된 것이며, 잠재적으로 때보다 훨씬 나중에 t # 39 isn& idfsysobject. 있지만 실제 오류가 발생했습니다.

요약:

  • 경우에만 사용 여부를 알아야 할 몇 가지 유형, 객체가 '는'.

  • 할 경우 특정 유형의 인스턴스를 로케이터로 처리하는 확장하지만 don& # 39, 확신할 수 있을지 알 수 없다 '를 사용하여 확인할지 객체에는 적립율은 해당 유형의' 와 'null'.

  • 로케이터로 인스턴스입니다 처리하는 할 경우 특정 유형 및 객체인지 있어야 사용하여 해당 유형의 일반 출연자.

해설 (2)

난 이미 속성 비교할 수 있도록 한 '유형' 과 '는' (like '는' my_type _basetypetolookfor) 사용할 수 없습니다, 하지만 난 이 사용할 수 있습니다.

base_type.IsInstanceOfType(derived_object);
base_type.IsAssignableFrom(derived_type);
derived_type.IsSubClassOf(base_type);

'리턴' 진정한 '' '와' 이사시냐블레프롬 이신스턴스로프티파 것을 볼 수 있는 반환되므로 아서브클라소프 비교할 때 같은 유형은 '거짓'. 여기서 '와' 아서브클라소프 인터페이스와도 작동하지 않는 다른 두 개의 책임질래. (참조 이 질문과 대답을).

public class Animal {}
public interface ITrainable {}
public class Dog : Animal, ITrainable{}

Animal dog = new Dog();

typeof(Animal).IsInstanceOfType(dog);     // true
typeof(Dog).IsInstanceOfType(dog);        // true
typeof(ITrainable).IsInstanceOfType(dog); // true

typeof(Animal).IsAssignableFrom(dog.GetType());      // true
typeof(Dog).IsAssignableFrom(dog.GetType());         // true
typeof(ITrainable).IsAssignableFrom(dog.GetType()); // true

dog.GetType().IsSubclassOf(typeof(Animal));            // true
dog.GetType().IsSubclassOf(typeof(Dog));               // false
dog.GetType().IsSubclassOf(typeof(ITrainable)); // false
해설 (0)

39, re you& 사용하는 경우 C # 7 관심용 업데이트하려면 Hare& # 39 의 멋지구리해요 앤드류 때가 답이다. 패턴 매칭 은 우리에게 주는 좋은 환경에서 짧은보기 입력되었는지 가변으로 if 문은 별도의 선언 없이 / 캐스팅 및 확인:

if (obj1 is int integerValue)
{
    integerValue++;
}

하지만 지금 이 예쁜 디자인 한 이 같은 캐스팅 실망 여러 개 있을 때 가능한 유형은상위 자위행위를 시화호로 들어오는 빛을 발한다. 이전 두 차례 피할 길은 아래 있다 "고 말했다.

Button button = obj1 as Button;
if (button != null)
{
    // do stuff...
    return;
}
TextBox text = obj1 as TextBox;
if (text != null)
{
    // do stuff...
    return;
}
Label label = obj1 as Label;
if (label != null)
{
    // do stuff...
    return;
}
// ... and so on

이 코드는 업으로 최대한 중복을 방지할 뿐만 아니라 방송 축소 같은 객체에는 항상 나를 괴롭혔다. 위의 아주 잘 압축됨 함께 패턴 매칭 다음과 같습니다.

switch (obj1)
{
    case Button button:
        // do stuff...
        break;
    case TextBox text:
        // do stuff...
        break;
    case Label label:
        // do stuff...
        break;
    // and so on...
}

편집: # 39 의 스위치를 사용할 수 있는 새로운 방법을 따라 Palec& 업데이트되도록 더 이상 언급은 하지 않았다.

해설 (3)

내가 &lt 포지셔닝하십시오 b&gt is&lt /b>;;;

즉,,, 사용하는 경우, re &lt you& # 39 b&gt is&lt /b&gt you& &lt em&gt not&lt /em>;;; re # 39 것으로 보인다. 상속을 사용하면 비판을 받아왔다.

Solaris. 사람이. 엔티티입니다 있는 및 동물: 엔티티입니다. 급지가 는 가상 메서드를 (company. 닐 행복하게 만들 수 있습니다)

<! - 언어: c # - &gt.

class Person
{
  // A Person should be able to Feed
  // another Entity, but they way he feeds
  // each is different
  public override void Feed( Entity e )
  {
    if( e is Person )
    {
      // feed me
    }
    else if( e is Animal )
    {
      // ruff
    }
  }
}

대답하도다

<! - 언어: c # - &gt.

class Person
{
  public override void Feed( Person p )
  {
    // feed the person
  }
  public override void Feed( Animal a )
  {
    // feed the animal
  }
}
해설 (6)

마지막 항목은 상속(예: Dog is Animal == true)도 살펴보는데, 대부분의 경우 이 항목이 더 낫다고 생각합니다.

해설 (0)

내가 하는 일에 따라 다릅니다. 부울 값이 필요한 경우(예를 들어, 정수로 캐스팅할지 여부를 결정하기 위해) is를 사용합니다. 다른 메서드에 전달하기 위해 어떤 이유로 유형이 실제로 필요한 경우 GetType()을 사용합니다.

해설 (1)

또한 하위 명백하네 더 클리너, 마지막 하나는 확인합니다. 다른 다형성 확인할지 마십시오.

해설 (0)

행하였 시스템스티페 입수합니다 객체 유형에 대해. A 는 다음과 같은 형식을 메리 페로프 표현식에서는.

System.Type type = typeof(int);

Example:

    public class ExampleClass
    {
       public int sampleMember;
       public void SampleMethod() {}

       static void Main()
       {
          Type t = typeof(ExampleClass);
          // Alternatively, you could use
          // ExampleClass obj = new ExampleClass();
          // Type t = obj.GetType();

          Console.WriteLine("Methods:");
          System.Reflection.MethodInfo[] methodInfo = t.GetMethods();

          foreach (System.Reflection.MethodInfo mInfo in methodInfo)
             Console.WriteLine(mInfo.ToString());

          Console.WriteLine("Members:");
          System.Reflection.MemberInfo[] memberInfo = t.GetMembers();

          foreach (System.Reflection.MemberInfo mInfo in memberInfo)
             Console.WriteLine(mInfo.ToString());
       }
    }
    /*
     Output:
        Methods:
        Void SampleMethod()
        System.String ToString()
        Boolean Equals(System.Object)
        Int32 GetHashCode()
        System.Type GetType()
        Members:
        Void SampleMethod()
        System.String ToString()
        Boolean Equals(System.Object)
        Int32 GetHashCode()
        System.Type GetType()
        Void .ctor()
        Int32 sampleMember
    */

이 예제 결과를 막기 위해 사용되는 게티페 유형을 결정하는 방법을 사용하여 숫자 계산. 이 결과 번호가 스트로지 요구 사항에 따라 달라집니다.

    class GetTypeTest
    {
        static void Main()
        {
            int radius = 3;
            Console.WriteLine("Area = {0}", radius * radius * Math.PI);
            Console.WriteLine("The type is {0}",
                              (radius * radius * Math.PI).GetType()
            );
        }
    }
    /*
    Output:
    Area = 28.2743338823081
    The type is System.Double
    */
해설 (0)
if (c is UserControl) c.Enabled = enable;
해설 (2)

&Quot &quot 메리 페로프 (), 사용할 수 있습니다. c # 에서 사용하는 데 필요한 연산자입니다 확장하지만 security. 이름공간이 시스템실리오; &Quot, is&quot 사용해야 합니다. 키워드 프로파일링하려는 경우 확인할지 유형입니다.

해설 (1)

성능 테스트 메리 페로프 () 와 게티페 ():

using System;
namespace ConsoleApplication1
    {
    class Program
    {
        enum TestEnum { E1, E2, E3 }
        static void Main(string[] args)
        {
            {
                var start = DateTime.UtcNow;
                for (var i = 0; i < 1000000000; i++)
                    Test1(TestEnum.E2);
                Console.WriteLine(DateTime.UtcNow - start);
            }
            {
                var start = DateTime.UtcNow;
                for (var i = 0; i < 1000000000; i++)
                    Test2(TestEnum.E2);
                Console.WriteLine(DateTime.UtcNow - start);
            }
            Console.ReadLine();
        }
        static Type Test1(T value) => typeof(T);
        static Type Test2(object value) => value.GetType();
    }
}

디버그 모드로 결과:

00:00:08.4096636
00:00:10.8570657

결과 릴리스에는 모드:

00:00:02.3799048
00:00:07.1797128
해설 (4)