대 typeof


150

이 코드들 중 어느 것이 더 빠릅니까?

if (obj is ClassA) {}

if (obj.GetType() == typeof(ClassA)) {}

편집 : 나는 그들이 똑같은 일을하지 않는다는 것을 알고 있습니다.


1
여기 비슷한 질문에 답변했습니다 : stackoverflow.com/questions/57701/…
— swilliams

답변:


167

이것은 그 질문에 답해야 할 것이고, 그 다음에 어떤 것이어야합니다.

두 번째 줄 if (obj.GetType() == typeof(ClassA)) {}은 기사를 읽고 싶지 않은 사람들에게는 빠릅니다.

(그들이 똑같은 일을하지 않는다는 것을 명심하십시오)


1
1 : 과거에는 C # 컴파일러가 컴파일되지 않은 이유가 궁금 typeof(string).TypeHandle받는 ldtokenCIL 명령하지만, CLR은 JIT에서 처리합니다 것 같습니다. 여전히 몇 가지 추가 opcode가 필요하지만 최적화의보다 일반적인 응용 프로그램입니다.
— Sam Harwell

2
higherlogics.blogspot.ca/2013/09/… 도 읽어보십시오. 다양한 프레임 워크와 x86 대 x64에 대해 다시 테스트하여 결과가 크게 다릅니다.
— CAD bloke

1
이는 참조 유형에만 해당됩니다. 그리고 속도 차이는 그다지 중요하지 않습니다. 에 대한 값 유형의 경우에 권투 처벌을 감안할 때 GetType, is성능에 관한 한 지금까지처럼 안전한 선택은 항상있다. 물론 그들은 다른 일을합니다.
— nawfal

Resharper에 넣으면 "is"로 변경하는 것이 좋습니다!
— Rob Sedgwick

@nawfal, 나는 처음에 권투 형벌에 대한 당신의 주장이 구조체 유형에 적합하다고 생각했지만 object obj;변수를 테스트하고 있다고 가정 할 때, 이것이 테스트 될 때 이미 박스되지 않습니까? 무언가의 유형을 테스트해야하는데 이미 오브젝트로 박스 화되어 있지 않은 경우가 있습니까?
— Rob Parker

193

그들이 같은 일을하지 않으면 더 빠른 것이 중요합니까? 다른 의미로 진술의 성과를 비교하는 것은 나쁜 생각처럼 보입니다.

is객체 ClassA가 유형 계층의 어느 곳에서나 구현되는지 알려줍니다 . GetType()가장 파생 된 유형에 대해 알려줍니다.

같은 것이 아닙니다.


7
내 경우에는 동일한 결과를 반환하기 때문에 중요합니다.
— ilitirit

37
@ [ilitirit] : 지금 같은 결과를 반환하지만 나중에 서브 클래스를 추가하면 그렇지 않습니다.
— Steven A. Lowe

13
지금 최적화하면 코드가 깨지기 쉽고 유지 관리가 어렵습니다.
— ICR

9
수업은 봉인되어 있습니다.
— ilitirit

26

그들은 같은 일을하지 않습니다. 첫 번째는 obj가 ClassA 유형이거나 ClassA의 일부 서브 클래스 인 경우 작동합니다. 두 번째는 ClassA 유형의 객체와 만 일치합니다. 두 번째는 클래스 계층 구조를 확인할 필요가 없기 때문에 더 빠릅니다.

이유를 알고 싶지만 다음에 언급 된 기사를 읽고 싶지 않은 사람들을 위해 vs typeof 입니다.


1
@amitjha 나는 그 테스트가 Mono에서 실행 되었기 때문에 기사에서 언급 된 JIT 최적화가 포함되어 있지 않다는 것에 약간 우려하고 있습니다. 기사가 그 반대를 보여 주므로 내 마음에 질문은 열려 있습니다. 어쨌든 유형에 따라 다른 작업을 수행하는 작업의 성능을 비교하는 것은 가치없는 연습으로 보입니다. "빠른"동작이 아닌 필요한 동작과 일치하는 작업을 사용하십시오.
— tvanfosson

16

나는 그들이 밀봉 유형을 동일하게하는 벤치마킹을했습니다.

var c1 = "";
var c2 = typeof(string);
object oc1 = c1;
object oc2 = c2;

var s1 = 0;
var s2 = '.';
object os1 = s1;
object os2 = s2;

bool b = false;

Stopwatch sw = Stopwatch.StartNew();
for (int i = 0; i < 10000000; i++)
{
    b = c1.GetType() == typeof(string); // ~60ms
    b = c1 is string; // ~60ms

    b = c2.GetType() == typeof(string); // ~60ms
    b = c2 is string; // ~50ms

    b = oc1.GetType() == typeof(string); // ~60ms
    b = oc1 is string; // ~68ms

    b = oc2.GetType() == typeof(string); // ~60ms
    b = oc2 is string; // ~64ms


    b = s1.GetType() == typeof(int); // ~130ms
    b = s1 is int; // ~50ms

    b = s2.GetType() == typeof(int); // ~140ms
    b = s2 is int; // ~50ms

    b = os1.GetType() == typeof(int); // ~60ms
    b = os1 is int; // ~74ms

    b = os2.GetType() == typeof(int); // ~60ms
    b = os2 is int; // ~68ms


    b = GetType1<string, string>(c1); // ~178ms
    b = GetType2<string, string>(c1); // ~94ms
    b = Is<string, string>(c1); // ~70ms

    b = GetType1<string, Type>(c2); // ~178ms
    b = GetType2<string, Type>(c2); // ~96ms
    b = Is<string, Type>(c2); // ~65ms

    b = GetType1<string, object>(oc1); // ~190ms
    b = Is<string, object>(oc1); // ~69ms

    b = GetType1<string, object>(oc2); // ~180ms
    b = Is<string, object>(oc2); // ~64ms


    b = GetType1<int, int>(s1); // ~230ms
    b = GetType2<int, int>(s1); // ~75ms
    b = Is<int, int>(s1); // ~136ms

    b = GetType1<int, char>(s2); // ~238ms
    b = GetType2<int, char>(s2); // ~69ms
    b = Is<int, char>(s2); // ~142ms

    b = GetType1<int, object>(os1); // ~178ms
    b = Is<int, object>(os1); // ~69ms

    b = GetType1<int, object>(os2); // ~178ms
    b = Is<int, object>(os2); // ~69ms
}

sw.Stop();
MessageBox.Show(sw.Elapsed.TotalMilliseconds.ToString());

제네릭 형식을 테스트하는 제네릭 함수 :

static bool GetType1<S, T>(T t)
{
    return t.GetType() == typeof(S);
}
static bool GetType2<S, T>(T t)
{
    return typeof(T) == typeof(S);
}
static bool Is<S, T>(T t)
{
    return t is S;
}

사용자 정의 유형도 시도했지만 결과는 일관되었습니다.

var c1 = new Class1();
var c2 = new Class2();
object oc1 = c1;
object oc2 = c2;

var s1 = new Struct1();
var s2 = new Struct2();
object os1 = s1;
object os2 = s2;

bool b = false;

Stopwatch sw = Stopwatch.StartNew();
for (int i = 0; i < 10000000; i++)
{
    b = c1.GetType() == typeof(Class1); // ~60ms
    b = c1 is Class1; // ~60ms

    b = c2.GetType() == typeof(Class1); // ~60ms
    b = c2 is Class1; // ~55ms

    b = oc1.GetType() == typeof(Class1); // ~60ms
    b = oc1 is Class1; // ~68ms

    b = oc2.GetType() == typeof(Class1); // ~60ms
    b = oc2 is Class1; // ~68ms


    b = s1.GetType() == typeof(Struct1); // ~150ms
    b = s1 is Struct1; // ~50ms

    b = s2.GetType() == typeof(Struct1); // ~150ms
    b = s2 is Struct1; // ~50ms

    b = os1.GetType() == typeof(Struct1); // ~60ms
    b = os1 is Struct1; // ~64ms

    b = os2.GetType() == typeof(Struct1); // ~60ms
    b = os2 is Struct1; // ~64ms


    b = GetType1<Class1, Class1>(c1); // ~178ms
    b = GetType2<Class1, Class1>(c1); // ~98ms
    b = Is<Class1, Class1>(c1); // ~78ms

    b = GetType1<Class1, Class2>(c2); // ~178ms
    b = GetType2<Class1, Class2>(c2); // ~96ms
    b = Is<Class1, Class2>(c2); // ~69ms

    b = GetType1<Class1, object>(oc1); // ~178ms
    b = Is<Class1, object>(oc1); // ~69ms

    b = GetType1<Class1, object>(oc2); // ~178ms
    b = Is<Class1, object>(oc2); // ~69ms


    b = GetType1<Struct1, Struct1>(s1); // ~272ms
    b = GetType2<Struct1, Struct1>(s1); // ~140ms
    b = Is<Struct1, Struct1>(s1); // ~163ms

    b = GetType1<Struct1, Struct2>(s2); // ~272ms
    b = GetType2<Struct1, Struct2>(s2); // ~140ms
    b = Is<Struct1, Struct2>(s2); // ~163ms

    b = GetType1<Struct1, object>(os1); // ~178ms
    b = Is<Struct1, object>(os1); // ~64ms

    b = GetType1<Struct1, object>(os2); // ~178ms
    b = Is<Struct1, object>(os2); // ~64ms
}

sw.Stop();
MessageBox.Show(sw.Elapsed.TotalMilliseconds.ToString());

그리고 유형 :

sealed class Class1 { }
sealed class Class2 { }
struct Struct1 { }
struct Struct2 { }

추론:

  1. 호출 GetType에 struct의 것은 느립니다. GetType은 object하위 유형으로 재정의 할 수없는 클래스에서 정의 되므로 struct호출하려면 boxed해야합니다 GetType.

  2. 객체 인스턴스에서는 GetType더 빠르지 만 매우 미미합니다.

  3. 제네릭 형식에, 경우 TIS class, 다음 is훨씬 빠릅니다. 경우 T이며 struct, 다음 is것보다 훨씬 빠르기 GetType하지만 typeof(T)훨씬 빠르게 모두보다. 의 경우에는 T존재 class, typeof(T)실제 기본 형태로부터 다른 이후 신뢰할 수 없습니다 t.GetType.

즉, object인스턴스 가있는 경우을 사용하십시오 GetType. 제네릭 class형식 인 경우을 사용하십시오 is. 제네릭 struct형식 인 경우을 사용하십시오 typeof(T). 제네릭 형식이 참조 형식 또는 값 형식인지 확실하지 않은 경우을 사용하십시오 is. 항상 하나의 스타일 (일관된 유형의 경우)과 일관성을 유지하려면 is..


1
실제로는 전혀 신경 쓰지 마십시오. 가장 적합한 것을 사용하십시오.
— nawfal
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.