2010-09-22 12 views
6

पिछले प्रश्न में आज इन दो अलग-अलग दृष्टिकोणों को उत्तर के रूप में एक प्रश्न के रूप में दिया गया था।कास्ट का उपयोग दो बार है, या एक बार के रूप में उपयोग करें और एक नया चर

हमारे पास एक ऐसा ऑब्जेक्ट है जो IDisposable को लागू या लागू नहीं कर सकता है। यदि ऐसा होता है, तो हम इसे निपटाना चाहते हैं, अगर हम कुछ भी नहीं करते हैं। दो अलग-अलग दृष्टिकोण ये हैं:

1)

if(toDispose is IDisposable) 
    (toDispose as IDisposable).Dispose(); 

2)

IDisposable disposable = toDispose as IDisposable; 
if(disposable != null) 
    disposable.Dispose(); 

मुख्य रूप से, टिप्पणी यह ​​आम सहमति की तरह लगता है से किया गया है कि 2) सबसे अच्छा तरीका था।

लेकिन मतभेद को देखते हुए, हम यह करने के लिए नीचे आ:

1) toDispose पर दो बार एक डाली निष्पादित करें।

2) केवल एक बार कास्ट करें, लेकिन एक नई मध्यवर्ती वस्तु बनाएं।

मुझे लगता है कि 2 मामूली धीमी होगी क्योंकि इसे एक नया स्थानीय चर आवंटित करना है, तो इसे इस मामले में सबसे अच्छा समाधान क्यों माना जाता है? यह पूरी तरह से पठनीयता मुद्दों के कारण है?

+0

एक तरफ ध्यान दें, मैं मध्यवर्ती चर के बारे में चिंता नहीं करता; एक बार जिटर के पास आपके कोड के साथ अपना रास्ता हो जाने के बाद, माइक्रो-ऑप्टिमाइज़ेशन के बारे में आपके द्वारा किए गए किसी भी अनुमान को अमान्य घोषित किया जा सकता है। –

उत्तर

12

मेरे कास्टिंग चारों ओर अंगूठे का नियम:

  • यदि यह एक त्रुटि/मूल्य नहीं सही प्रकार के होने के लिए बग है, बस
  • डाली अन्यथा अपने दूसरे मामले में as, की तरह का उपयोग
  • आप एक मान प्रकार साथ काम कर रहे हैं, तो आप as उपयोग कर सकते हैं नल प्रकार (स्थिरता के लिए) के साथ या is का उपयोग करें और एक सीधा डाली

ध्यान दें कि आपका दूसरा फॉर्म कोई "नया इंटरमीडिएट ऑब्जेक्ट" नहीं बनाता है। यह एक नया इंटरमीडिएट परिवर्तनीय बनाता है। तो क्या आपका पहला दृष्टिकोण वास्तव में है - यह सिर्फ इतना है कि परिवर्तक संकलक द्वारा प्रभावी रूप से छिपा हुआ है। यह अभी भी आईएल में एक स्टैक स्थान के रूप में मौजूद है, लेकिन इसका स्रोत कोड में कोई प्रतिनिधित्व नहीं है।

यह सब कहकर, में यह विशेष मामला (जहां आप बस निपटाना चाहते हैं), डारिन का दृष्टिकोण सबसे अच्छा है, मुझे विश्वास है।

+0

+1 सीधे डालने का सुझाव देने के लिए। मैंने बहुत सारे कोड देखे हैं जहां लोग अस्थायी रूप से अमान्य कैस्टएक्सप्शन/NullReferenceException को संभाल/छोड़ देते हैं, वास्तव में इसे फेंक दिया जाना चाहिए क्योंकि यह वास्तव में * एक त्रुटि है। – bitbonk

+0

मुझे अच्छे नियमों की तरह लगता है। मुझे पता नहीं था कि पहला संस्करण भी वें दृश्यों के पीछे एक चर बनाता है, इसलिए यह वास्तव में कोई ब्रेनर नहीं है और 2) जाने का तरीका है। –

+0

और यह इंटरमीडिएट वैरिएबल था जो मैं सोच रहा था, लेकिन किसी कारण से इसे इंटरमीडिएट ऑब्जेक्ट के रूप में लिखा गया। मुझे पता है कि यह ढेर पर एक नई वस्तु नहीं बना है, लेकिन ढेर पर एक नया चर। बहुत धन्यवाद श्री स्कीट। –

13

नहीं वास्तव में आपके सवाल का जवाब लेकिन मैं आपको इस संरचना की सिफारिश करेंगे:

using (toDispose as IDisposable) 
{ 
    ... 
} 

और ifs, finally और Dispose कॉल के बारे में संकलक चिंता करते हैं।

+0

+1। बस (toDispose) का उपयोग करके कहने के लिए पर्याप्त है, क्योंकि यह केवल तभी निपटान होगा जब यह पहचान योग्य हो। – eglasius

+0

@ एग्लासियस, लेकिन यह 'toDispose' के प्रकार के आधार पर संकलित नहीं हो सकता है। उदाहरण के लिए: 'ऑब्जेक्ट टू डिस्प्ले = FetchSomeDisposableResource(); '। –

+0

यह सही है, मैं वास्तव में इसे दो बार चेक किया। मेरी याददाश्त विफल रही, मुझे बहुत समय पहले ऐसा करने को याद आया, लेकिन मुझे लगता है कि मैंने एक आईडीस्पोज़ेबल के रूप में भी इस्तेमाल किया होगा ... और वास्तव में शून्य के अनदेखा करने वाले उपयोग कथन के बारे में था। – eglasius

4

इसे एक बेहतर समाधान के रूप में माना जाता है क्योंकि परिवर्तनीय आवंटन को कास्ट से तेज़ माना जाता है। इसके अतिरिक्त, कलाकार को संकलक द्वारा संभावित रूप से अनुकूलित किया जा सकता है।

किसी भी तरह से, यह वैसे भी microoptimizing है। उस कोड का उपयोग करें जो आपको लगता है कि बनाए रखने के लिए सबसे आसान है।

2

दूसरा विकल्प वास्तव में कुछ हद तक तेज़ है। स्थानीय व्यवहार्यता तक पहुंचने के लिए अतिरिक्त कलाकारों को करने में अधिक समय लगता है।

स्थानीय चर आवंटित करना धीमा नहीं है। असल में इसमें कोई समय नहीं लगता है।

जब कोई विधि दर्ज की जाती है, तो स्टैक फ्रेम को विधि में स्थानीय डेटा के लिए स्थान आवंटित करने के लिए स्टैक पॉइंटर को स्थानांतरित करके बनाया जाता है। स्टैक पॉइंटर से बड़ी संख्या घटाने में अधिक समय नहीं लगता है, इसलिए स्थानीय चर के लिए स्थान आवंटित करने में कोई समय नहीं लगता है। और यह लगभग कोई समय नहीं है, लेकिन वास्तव में शून्य समय है।

स्थानीय चर की एकमात्र लागत यह है कि आप स्टैक स्पेस का उपयोग कर रहे हैं, लेकिन चूंकि यह केवल एक मेगाबाइट (आईआईआरसी) स्टैक से कुछ बाइट्स है, यह तब तक कोई समस्या नहीं है जब तक कि आप गहरी रिकर्सिव कॉल नहीं कर रहे हों।

इसके अलावा, यदि आवश्यक हो तो संकलक स्थानीय चर बना सकता है, इसलिए यह भी संभव है कि दोनों विधियां अंत में स्थानीय चर का उपयोग करके समाप्त हो जाएं।

1

यहां प्रतिबिंब कार्य का भी उपयोग करना होगा या as का उपयोग करने की तुलना में धीमा होना होगा?

मैंने 2 कक्षाएं बनाई हैं, एक नाम ICanDispose है जो IDisposable लागू करता है और दूसरा ICanNotDisposeIDisposable लागू नहीं करता है।

मेरे ICanDispose कक्षा में मैं प्रतिबिंब जांचने के लिए बस एक संदेश बॉक्स दिखाता हूं वास्तव में Dispose विधि का आह्वान किया है।

मेरे पास नीचे दिए गए कोड को निष्पादित करने वाले मेरे फॉर्म पर एक बटन है। प्रतिबिंबों का उपयोग करके यह जांचता है कि क्या मेरा ऑब्जेक्ट IDisposable इंटरफ़ेस लागू करता है और यदि ऐसा है तो Dispose विधि को आमंत्रित करता है।

private void button1_Click(object sender, EventArgs e) 
{ 
    ICanDispose myObject1 = new ICanDispose(); 
    ICanNotDispose myObject2 = new ICanNotDispose(); 

    // Checking object 1 which does implement IDisposable. 
    if (myObject1.GetType().GetInterface("IDisposable", true) != null) 
    { 
     myObject1.GetType().InvokeMember(
      "Dispose", 
      System.Reflection.BindingFlags.Default | System.Reflection.BindingFlags.InvokeMethod, 
      null, 
      Activator.CreateInstance(myObject1.GetType()), 
      null); 
    } 

    // Checking object 2 which does not implement IDisposable.  
    if (myObject2.GetType().GetInterface("IDisposable", true) != null) 
    { 
     myObject2.GetType().InvokeMember(
      "Dispose", 
      System.Reflection.BindingFlags.Default | System.Reflection.BindingFlags.InvokeMethod, 
      null, 
      Activator.CreateInstance(myObject2.GetType()), 
      null); 
    } 
} 
1

कोई भी यहाँ उल्लेख किया है कि FxCop पहले approch के मामले में एक DoNotCastUnnecessarily चेतावनी दिखाता है। इस नियम के लिए सहायता पहले

के स्थान पर दूसरा दृष्टिकोण का सुझाव http://msdn.microsoft.com/en-us/library/ms182271(VS.90).aspx

डुप्लिकेट डाले प्रदर्शन, खासकर जब डाले कॉम्पैक्ट यात्रा बयान में प्रदर्शन कर रहे हैं नीचा। स्पष्ट डुप्लिकेट कास्ट ऑपरेशंस के लिए, स्थानीय चर में का परिणाम संग्रहित करें और डुप्लिकेट कास्ट ऑपरेशंस के बजाय स्थानीय चर का उपयोग करें।

सी # ऑपरेटर परीक्षण करने के लिए है कि क्या डाली सफल होगा से पहले वास्तविक कलाकारों किया जाता है, ऑपरेटर बजाय के रूप में के परिणाम का परीक्षण पर विचार किया जाता है जाता है। यह ऑपरेटर द्वारा निष्पादित कास्ट ऑपरेशन के बिना कार्यक्षमता प्रदान करता है।

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