मुझे पहले इसे बाहर करने दो और इसके बाद वापस आओ:
जब आप किसी ऑब्जेक्ट पर टैब रखना चाहते हैं तो एक WeakReference उपयोगी है, लेकिन आप उस ऑब्जेक्ट को एकत्र होने से रोकने के लिए अपनी टिप्पणियों को नहीं चाहते हैं
तो शुरू से शुरू करते हैं:
- अग्रिम में किसी भी अनजाने अपराध के लिए, लेकिन मैं एक पल के लिए "डिक और जेन" स्तर पर वापस आने वाला हूं क्योंकि कोई भी दर्शकों को कभी नहीं बता सकता है।
इसलिए जब आपको कोई वस्तु मिल गई है X
- चलो इसे एक उदाहरण के रूप में निर्दिष्ट करते हैं class Foo
- यह अपने आप पर नहीं रह सकता है (ज्यादातर सच); उसी तरह से कि "कोई आदमी एक द्वीप नहीं है", केवल कुछ ही तरीके हैं जो एक वस्तु को द्वीपवाद को बढ़ावा दे सकते हैं - हालांकि इसे सीएलआर बोलते में जीसी रूट कहा जाता है। जीसी रूट होने के नाते, या जीसी रूट के कनेक्शन / संदर्भों की एक स्थापित श्रृंखला होने के नाते, मूल रूप से यह निर्धारित करता है कि Foo x = new Foo()
कचरा एकत्र होता है या नहीं ।
यदि आप अपने जीसी रूट पर वापस नहीं जा सकते हैं तो या तो ढेर या स्टैक वॉकिंग से, आप प्रभावी रूप से अनाथ हैं, और संभवतः अगले चक्र को चिह्नित / एकत्र किया जाएगा।
इस बिंदु पर, आइए कुछ भयानक-आकस्मिक उदाहरण देखें:
सबसे पहले, हमारे Foo
:
public class Foo
{
private static volatile int _ref = 0;
public event EventHandler FooEvent;
public Foo()
{
_ref++;
Console.WriteLine("I am #{0}", _ref);
}
~Foo()
{
Console.WriteLine("#{0} dying!", _ref--);
}
}
बहुत आसान है - यह थ्रेड सुरक्षित नहीं है, इसलिए कोशिश मत करो, लेकिन जब वे अंतिम रूप से सक्रिय उदाहरणों और गिरावटों की एक "संदर्भ गणना" रखते हैं।
अब एक नजर डालते हैं FooConsumer
:
public class NastySingleton
{
// Static member status is one way to "get promoted" to a GC root...
private static NastySingleton _instance = new NastySingleton();
public static NastySingleton Instance { get { return _instance;} }
// testing out "Hard references"
private Dictionary<Foo, int> _counter = new Dictionary<Foo,int>();
// testing out "Weak references"
private Dictionary<WeakReference, int> _weakCounter = new Dictionary<WeakReference,int>();
// Creates a strong link to Foo instance
public void ListenToThisFoo(Foo foo)
{
_counter[foo] = 0;
foo.FooEvent += (o, e) => _counter[foo]++;
}
// Creates a weak link to Foo instance
public void ListenToThisFooWeakly(Foo foo)
{
WeakReference fooRef = new WeakReference(foo);
_weakCounter[fooRef] = 0;
foo.FooEvent += (o, e) => _weakCounter[fooRef]++;
}
private void HandleEvent(object sender, EventArgs args, Foo originalfoo)
{
Console.WriteLine("Derp");
}
}
इसलिए हमें एक ऐसी वस्तु मिल गई है जो पहले से ही इसकी एक जीसी जड़ है। एक Foo
उदाहरण पर लाचिंग - चलो इसे बाहर का परीक्षण करें:
// Our foo
var f = new Foo();
// Create a "hard reference"
NastySingleton.Instance.ListenToThisFoo(f);
// Ok, we're done with this foo
f = null;
// Force collection of all orphaned objects
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
अब, ऊपर से, आप f
"संग्रहणीय" होने के लिए वस्तु-कि-एक-बार-संदर्भित-से-उम्मीद करेंगे ?
नहीं, क्योंकि एक अन्य वस्तु है जो अब इसका संदर्भ रखती है - Dictionary
उस Singleton
स्थिर उदाहरण में।
ठीक है, चलो कमजोर दृष्टिकोण की कोशिश करें:
f = new Foo();
NastySingleton.Instance.ListenToThisFooWeakly(f);
// Ok, we're done with this foo
f = null;
// Force collection of all orphaned objects
// This should collect # 2 - you'll see a "#2 dying"
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
अब, जब हम अपने संदर्भ को Foo
-that-was-Once-one- से जोड़ते f
हैं, तो ऑब्जेक्ट के लिए अधिक "कठिन" संदर्भ नहीं होते हैं, इसलिए यह संग्रहणीय है - WeakReference
कमजोर श्रोता द्वारा बनाया गया यह रोक नहीं पाएगा।
अच्छे उपयोग के मामले:
ईवेंट हैंडलर (हालाँकि इसे पहले पढ़ें: C # में कमजोर ईवेंट )
आपको एक ऐसी स्थिति मिली है जहाँ आप एक "पुनरावर्ती संदर्भ" (यानी, ऑब्जेक्ट A को ऑब्जेक्ट B से संदर्भित करते हैं, जो ऑब्जेक्ट A को संदर्भित करता है, जिसे "मेमोरी लीक" भी कहा जाता है) (संपादित करें: derp, बेशक यह isn है 'सच है)
आप वस्तुओं के संग्रह के लिए कुछ "प्रसारित" करना चाहते हैं, लेकिन आप उन्हें जीवित रखने वाली चीज नहीं बनना चाहते; एक List<WeakReference>
को आसानी से बनाए रखा जा सकता है, और यहां तक कि जहां हटाकर छंटाई की जा सकती हैref.Target == null