2013-07-21 7 views
6

विभिन्न प्रकार के लिए 100 बार फ़ंक्शन ओवरलोड करने या 100 अलग-अलग तुलना करने वाले के बजाय मैंने एक फ़ंक्शन के भीतर प्रकार को जांचने का निर्णय लिया है।एक प्रकार की जांच करने का सबसे तेज़ तरीका क्या है?

उदाहरण के लिए मैं 2 ऑब्जेक्ट्स के भीतर प्रकारों (प्राइमेटिव्स और स्ट्रिंग्स) के मानों की तुलना करने के लिए एक डिफ़ॉल्ट तुलनाकर्ता का उपयोग कर रहा हूं।

public class DefComparer : IComparer<object> { 
    public int Compare(object a, object b) { 
     .... // a = a.GetType().GetField(field).GetValue(a); - not important for the question but I'm just showing that a&b below are different references 
     switch (a.GetType().Name) { 
      case "Byte": 
       if ((byte)a == (byte)b) return 0; 
       else if ((byte)a > (byte)b) return 1; 
       else return -1; 
      case "UInt16": 
       if ((ushort)a == (ushort)b) return 0; 
       else if ((ushort)a > (ushort)b) return 1; 
       else return -1; 
      case "SByte": 
       if ((sbyte)a == (sbyte)b) return 0; 
       else if ((sbyte)a > (sbyte)b) return 1; 
       else return -1; 
      case "Int16": 
       ... 

यहाँ मैं एक switch बयान if/else बयान की एक श्रृंखला की तुलना में तेजी होने के लिए कहा जाता है कि उपयोग कर रहा हूँ: यह निम्नलिखित कोड शामिल हैं। लेकिन a.GetType().Name एक स्ट्रिंग देता है जो गतिशील रूप से प्राप्त होता है और इस विधि में स्ट्रिंग तुलना शामिल होती है। यह मेरे लिए विशेष रूप से तेज़ नहीं लगता है। मुझे तुलनात्मक रूप से तुलनात्मक रूप से तुलना करने की आवश्यकता है क्योंकि यह डेटा के बड़े संग्रह पर उपयोग किया जा रहा है।

प्रश्न: क्या किसी ऑब्जेक्ट के प्रकार को जांचने का कोई तेज़ तरीका है (जिसमें स्ट्रिंग तुलना शामिल नहीं है)? सबसे तेज़ संभव तरीका क्या है?

+1

आप 'तुलनाकर्ता.डिफॉल्ट' की तलाश में हैं। – SLaks

+0

या कॉल ((IComparable) ए) .CompareTo (बी) – usr

+0

नहीं, मैं 'तुलनाकर्ता.फॉल्ट' की तलाश नहीं कर रहा हूं। मैंने इसे और अधिक स्पष्ट करने के लिए अपनी पोस्ट संपादित की है। मेरा सवाल एक प्रकार की जांच करने के लिए एक तेज़ तरीका है। – brandon

उत्तर

6

ठीक है आपके पास यह आपके हाथ में है। TypeCode

 int a = 10; 
     Type t = a.GetType(); 

     switch (Type.GetTypeCode(t)) 
     { 
      case TypeCode.Boolean: 
       break; 
      case TypeCode.Byte: 
       break; 
      case TypeCode.Char: 
       break; 
      case TypeCode.DBNull: 
       break; 
      case TypeCode.DateTime: 
       break; 
      case TypeCode.Decimal: 
       break; 
      case TypeCode.Double: 
       break; 
      case TypeCode.Empty: 
       break; 
      case TypeCode.Int16: 
       break; 
      case TypeCode.Int32: 
       break; 
      case TypeCode.Int64: 
       break; 
      case TypeCode.Object: 
       break; 
      case TypeCode.SByte: 
       break; 
      case TypeCode.Single: 
       break; 
      case TypeCode.String: 
       break; 
      case TypeCode.UInt16: 
       break; 
      case TypeCode.UInt32: 
       break; 
      case TypeCode.UInt64: 
       break; 
      default: 
       break; 
     } 

यह सभी प्राइमेटिव का समर्थन करता है। कस्टम ऑब्जेक्ट्स के लिए TypeCode.Object के अंदर बयान लिखें।

मुझे उम्मीद है कि इससे मदद मिलती है।

+0

हां, परीक्षण दिखाते हैं कि आपकी विधि तेज है। मुझे 'टाइपकोड' एनम के बारे में पता नहीं था। – brandon

+0

@ ब्रैंडन चीयर्स, अब आप इसके बारे में जानते हैं। –

+0

@ ब्रैंडन मैं आपको उपयुक्त प्रकार में डालने और इसे स्थानीय चर में स्टोर करने का सुझाव देता हूं, फिर 'अनबॉक्सिंग' के बजाय प्रदर्शन के लिए तुलना करें –

3

टिप्पणियों से, ऐसा लगता है कि आपके पास अलग-अलग प्रकार के सबबजेक्ट के साथ संरचित डेटा का एक गुच्छा है।

यदि संग्रह बड़े होते हैं, तो सबसे तेज़ तरीका डायनामिक कोडेजन (अभिव्यक्ति पेड़ के साथ) एक एकल विधि बनाने के लिए होगा जो दृढ़ता से टाइप किए गए तरीके से सभी फ़ील्ड/गुणों को खींचता है और दृढ़ता से टाइप की गई तुलना करता है।

असल में, आप संग्रह सदस्य प्रकार से क्षेत्र/संपत्ति प्रकार गतिशील रूप से प्राप्त करने के लिए प्रतिबिंब का उपयोग करते हैं। फिर आप MemberAccessExpression अभिव्यक्तियों का निर्माण करते हैं, उन्हें Expression.Equal पर पास करें, और सभी परिणाम Expression.AndAlso पर जाएं। अभिव्यक्ति संकलन आपको एक प्रतिनिधि प्रदान करता है जो संग्रह में निहित विशेष प्रकार की दो वस्तुएं लेता है।

स्टार्टअप समय आपके प्रश्न में दिखाए गए कोड से धीमी गति के कुछ आदेश होंगे, लेकिन लागत प्रति वस्तु बहुत कम होगी। आपको यह देखने के लिए परीक्षण करना होगा कि ब्रेकवेन पॉइंट कहां है - लेकिन शायद कम हजारों में।

संबंधित मुद्दे