बनाम टाइपोफ़ है


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 # कंपाइलर CIL इंस्ट्रक्शन typeof(string).TypeHandleको कंपाइल क्यों नहीं ldtokenकरता, लेकिन ऐसा लगता है कि CLR JIT में इसकी देखभाल करता है। यह अभी भी कुछ अतिरिक्त ऑपकोड लेता है, लेकिन यह अनुकूलन का अधिक सामान्यीकृत अनुप्रयोग है।
सैम हरवेल

2
हाइलोग्राफिक्स पढ़ें .blogspot.ca/2013/09/ … - भी - वे अलग-अलग चौखटे और x86 बनाम x64 के लिए व्यापक रूप से अलग-अलग परिणामों के साथ फिर से संगठित होते हैं।
सीएडी

1
कृपया ध्यान दें कि यह केवल संदर्भ प्रकारों के लिए सत्य है। और गति अंतर इतना महत्वपूर्ण नहीं है। मूल्य प्रकारों के मामले में मुक्केबाजी दंड को देखते हुए GetType, isजहां तक ​​प्रदर्शन का संबंध है , हमेशा सुरक्षित विकल्प है। बेशक वे अलग-अलग चीजें करते हैं।
नवाफाल

अगर आप इसे Resharper में डालते हैं तो इसे "is" में बदलने का सुझाव देते हैं!
Rob Sedgwick

@nawfal, मैंने शुरू में सोचा था कि बॉक्सिंग पेनल्टी के बारे में संरचनात्मक प्रकारों के लिए समझ में आता है, लेकिन यह देखते हुए कि हम एक object obj;चर का परीक्षण कर रहे हैं , क्या यह पहले से ही बॉक्सिंग नहीं है जब यह परीक्षण किया जाता है? क्या कोई ऐसा मामला है जहां आपको किसी चीज़ के प्रकार का परीक्षण करने की आवश्यकता है और यह पहले से ही एक वस्तु के रूप में बॉक्सिंग नहीं है?
रॉब पार्कर

193

क्या इससे कोई फर्क नहीं पड़ता, अगर वे एक ही काम नहीं करते हैं? विभिन्न अर्थों के साथ बयानों के प्रदर्शन की तुलना करना एक बुरा विचार है।

isआपको बताता है कि क्या वस्तु ClassAअपने प्रकार के उत्तराधिकार में कहीं भी लागू होती है । GetType()आपको सबसे अधिक व्युत्पन्न प्रकार के बारे में बताता है।

एक ही बात नहीं है।


7
यह मायने रखता है, क्योंकि मेरे मामले में मैं सकारात्मक हूं वे उसी परिणाम को वापस करते हैं।
ilitirit

37
@ [ilitirit]: वे अभी एक ही परिणाम लौटाते हैं, लेकिन यदि आप बाद में उपवर्ग जोड़ते हैं तो वे नहीं
स्टीवन ए। लोव

13
अब अनुकूलन करना आपके कोड को भंगुर और बनाए रखना मुश्किल बना देगा।
ICR

9
मेरी कक्षाएं सील हैं।
इलीटिरिट

26

वे एक ही काम नहीं करते। पहले एक काम करता है अगर obj टाइप क्लास का है या क्लास ए के कुछ उपवर्गों का है। दूसरा केवल टाइप क्लासए की वस्तुओं से मेल खाएगा। दूसरा तेजी से होगा क्योंकि इसमें कक्षा पदानुक्रम की जांच नहीं होती है।

उन लोगों के लिए जो इसका कारण जानना चाहते हैं, लेकिन संदर्भित लेख को पढ़ना नहीं चाहते हैं बनाम टाइपोफ़ है


1
@amitjha मैं थोड़ा चिंतित हूं क्योंकि वह परीक्षण मोनो के तहत चलाया गया था कि इसमें लेख में संदर्भित जेआईटी अनुकूलन शामिल नहीं है। चूंकि लेख विपरीत दिखाता है, मेरे दिमाग में सवाल एक खुला है। किसी भी घटना में, प्रकार के आधार पर अलग-अलग चीजें करने वाले संचालन के प्रदर्शन की तुलना करना एक बेकार अभ्यास लगता है। उस ऑपरेशन का उपयोग करें जो आपके लिए आवश्यक व्यवहार से मेल खाता है, न कि "तेज" है
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. S GetTypeपर कॉल structकरना धीमा है। वर्ग GetTypeपर परिभाषित किया गया है objectजिसे उप प्रकारों में ओवरराइड नहीं किया जा सकता है और इस तरह structसे बॉक्सिंग करने की आवश्यकता होती है GetType

  2. एक वस्तु उदाहरण पर, GetTypeतेज है, लेकिन बहुत मामूली है।

  3. जेनेरिक प्रकार पर, यदि Tहै class, तो isबहुत तेज है। यदि Tहै struct, तो isबहुत तेजी से है, GetTypeलेकिन typeof(T)दोनों की तुलना में बहुत तेज है। Tहोने के मामलों में class, typeof(T)वास्तविक अंतर्निहित प्रकार से अलग होने के बाद से विश्वसनीय नहीं है t.GetType

संक्षेप में, यदि आपके पास एक objectउदाहरण है, तो उपयोग करें GetType। यदि आपके पास सामान्य classप्रकार है, तो उपयोग करें is। यदि आपके पास सामान्य structप्रकार है, तो उपयोग करें typeof(T)। यदि आप अनिश्चित हैं यदि सामान्य प्रकार संदर्भ प्रकार या मान प्रकार है, तो उपयोग करें is। यदि आप हमेशा एक शैली के अनुरूप होना चाहते हैं (सील प्रकारों के लिए), तो उपयोग करें is..


1
वास्तव में, बिल्कुल भी परवाह नहीं है। जो सबसे अधिक समझ में आता है उसका उपयोग करें।
नवाफाल
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.