대 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. 호출 GetTypestruct의 것은 느립니다. GetTypeobject하위 유형으로 재정의 할 수없는 클래스에서 정의 되므로 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.