[C#] 대 typeof

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

if (obj is ClassA) {}

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

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



답변

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

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

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


답변

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

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

같은 것이 아닙니다.


답변

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

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


답변

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

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..


답변