2011-12-29 7 views
10

के माइक्रोसॉफ्ट के कार्यान्वयन को समझने के लिए एक अनुभवी सी ++ प्रोग्रामर नेट के आदी प्राप्त करने की कोशिश के रूप में की कोशिश कर रहा है, वहाँ संपत्ति माइक्रोसॉफ्ट के WeakReference "लक्ष्य" में एक कार्यान्वयन विस्तार है कि मुझे गुस्सा दिलाना है ...WeakReference

public class WeakReference : ISerializable 
{ 
    internal IntPtr m_handle; 
    internal bool m_IsLongReference; 
       ... 
    public virtual object Target 
    { 
     [SecuritySafeCritical] 
     get 
     { 
      IntPtr handle = this.m_handle; 
      if (IntPtr.Zero == handle) 
      { 
       return null; 
      } 
      object result = GCHandle.InternalGet(handle); 
      if (!(this.m_handle == IntPtr.Zero)) 
      { 
       return result; 
      } 
      return null; 
     } 
     [SecuritySafeCritical] 
     set 
     { 
      IntPtr handle = this.m_handle; 
      if (handle == IntPtr.Zero) 
      { 
       throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_HandleIsNotInitialized")); 
      } 
      object oldValue = GCHandle.InternalGet(handle); 
      handle = this.m_handle; 
      if (handle == IntPtr.Zero) 
      { 
       throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_HandleIsNotInitialized")); 
      } 
      GCHandle.InternalCompareExchange(handle, value, oldValue, false); 
      GC.KeepAlive(this); 
     } 
    } 
    ... 
     } 

बात है कि मुझे परेशान करना यह है - वे दो बार m_handle की वैधता की जांच क्यों कर रहे हैं? विशेष रूप से 'सेट' विधि में - विधि के अंत में GC.KeepAlive के उपयोग की जा रही कचरा एकत्र से WeakReference रखना चाहिए, और इस तरह संभाल रखने गैर शून्य - है ना?

और इन के मामले 'प्राप्त' - एक बार हम वास्तव में, InternalGet के माध्यम से लक्ष्य के लिए एक संदर्भ लिया गया गया है क्यों मूल m_handle मूल्य फिर से जाँच परेशान? , लेकिन निश्चित रूप से यह भी निपटारा नहीं किया जा सका और अंतिम रूप दिया इससे पहले कि हम वस्तु लौटने के लिए चारों ओर पाने के - सभी मुझे लगता है कि कर सकते हैं कि शायद वे WeakReference से सुरक्षा के लिए निपटाया और के दौरान या InternalGet बाद अंतिम रूप दिया जा रहा है की कोशिश कर रहे है? मैं सिर्फ डब्ल्यू/क्यों इस तरह जांचना यहाँ आवश्यक है के रूप में एक वैध स्पष्टीकरण आया नहीं कर सकते हैं ...

+0

आप कार्यान्वयन इतना क्यों ध्यान करते हैं? और क्या यह वास्तविक माइक्रोसॉफ्ट लाइसेंस प्राप्त कोड है जिसे आप पोस्ट कर रहे हैं, या क्या यह मोनो है? – Dykam

+0

+1 अच्छा सवाल। किसी भी एक्सेसर्स में ज्यादा समझ में नहीं आता है। – Groo

+7

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

उत्तर

8

सभी मुझे लगता है कि कर सकते हैं कि शायद वे निपटारा किया जा रहा WeakReference से बचाव की कोशिश कर रहे है और के दौरान या उसके बाद अंतिम रूप दिया गया आंतरिक गेट

यह बिल्कुल सही है।

लेकिन निश्चित रूप से, क्या यह ऑब्जेक्ट लौटने के लिए लगभग को डिस्पोजेड और अंतिम रूप दिया जा सकता था?

नहीं, क्योंकि उस बिंदु पर, ऑब्जेक्ट में एक मजबूत सूचक बनाया जाना चाहिए था। InternalGet एक मजबूत सूचक देता है, और अगर है कि मजबूत सूचक, oldValue में संग्रहीत, वस्तु के लिए है, अब वस्तु नहीं रह गया कचरा कलेक्टर द्वारा पुन: दावा किया जा सकता है।

+0

'InternalGet 'पर कॉल मजबूत सूचक बनने के लिए नहीं है, लेकिन जो भी कार्यान्वयन है। –

+0

@TomislavMarkovski इसे प्रभावी ढंग से करता है, के रूप में यह वस्तु 'GCHandle' (वापसी मान) में संदर्भित करने के लिए एक रूट बनाने है। एक बार जब आप रिटर्न वैल्यू (पुराना वैल्यू) स्टोर करते हैं, तो आपके पास रूट जीसी संदर्भ है, इसलिए ऑब्जेक्ट अब जीसी के लिए योग्य नहीं है। –

+0

धन्यवाद! फिर भी - मुझे तर्क दिखाई नहीं देता है। एकमात्र चीज जो आंतरिक संभाल को शून्य कर सकती है वह अंतिमकर्ता है - इसलिए इस कॉल के दौरान हैंडल को बदलने का एकमात्र तरीका यह है कि यदि वीक रेफरेंस के फाइनलाइज़र को रास्ते में बुलाया जाता है। आइए मान लें कि मेरे पास उन "ज़ोंबी" वीक रेफरेंस में से एक है वीक रेफरेंस - इसलिए मैं इसके अंतिमकरण के बाद इस वीक रेफरेंस पर "प्राप्त" कहता हूं। फिर भी - एकमात्र तरीका है कि हैंडल पर दूसरी जांच में अंतर हो सकता है यदि डब्ल्यूआर के फाइनलाइज़र को पहले और दूसरे चेक के बीच कहीं भी कहा जाता है। – Kevin