आप आसानी से WeakList<T>
कक्षा लागू कर सकते हैं, जो List<WeakReference>
को लपेट देगा।
कचरा इकट्ठा होने पर वस्तुओं को स्वचालित रूप से निकालने का कोई तरीका नहीं है, क्योंकि ऐसा होने पर यह पता लगाना संभव नहीं है। हालांकि, WeakReference.IsAlive
संपत्ति की जांच करके, जब आप उन्हें सामना करते हैं तो आप "मृत" (कचरा एकत्रित) वस्तुओं को निकाल सकते हैं। हालांकि, मैं इस दृष्टिकोण की अनुशंसा नहीं करता, क्योंकि इससे ग्राहक के दृष्टिकोण से भ्रमित व्यवहार हो सकता है। इसके बजाय, मैं मृत प्रविष्टियों को हटाने के लिए Purge
विधि को लागू करने की अनुशंसा करता हूं, जिसे आप स्पष्ट रूप से कॉल करेंगे।
WeakReference<T>
(WeakReference
चारों ओर सिर्फ एक दृढ़ता से टाइप किया आवरण)
[Serializable]
public class WeakReference<T> : WeakReference
{
public WeakReference(T target)
: base(target)
{
}
public WeakReference(T target, bool trackResurrection)
: base(target, trackResurrection)
{
}
public WeakReference(SerializationInfo info, StreamingContext context)
: base(info, context)
{
}
public new T Target
{
get
{
return (T)base.Target;
}
}
}
:
public class WeakList<T> : IList<T>
{
private List<WeakReference<T>> _innerList = new List<WeakReference<T>>();
#region IList<T> Members
public int IndexOf(T item)
{
return _innerList.Select(wr => wr.Target).IndexOf(item);
}
public void Insert(int index, T item)
{
_innerList.Insert(index, new WeakReference<T>(item));
}
public void RemoveAt(int index)
{
_innerList.RemoveAt(index);
}
public T this[int index]
{
get
{
return _innerList[index].Target;
}
set
{
_innerList[index] = new WeakReference<T>(value);
}
}
#endregion
#region ICollection<T> Members
public void Add(T item)
{
_innerList.Add(new WeakReference<T>(item));
}
public void Clear()
{
_innerList.Clear();
}
public bool Contains(T item)
{
return _innerList.Any(wr => object.Equals(wr.Target, item));
}
public void CopyTo(T[] array, int arrayIndex)
{
_innerList.Select(wr => wr.Target).CopyTo(array, arrayIndex);
}
public int Count
{
get { return _innerList.Count; }
}
public bool IsReadOnly
{
get { return false; }
}
public bool Remove(T item)
{
int index = IndexOf(item);
if (index > -1)
{
RemoveAt(index);
return true;
}
return false;
}
#endregion
#region IEnumerable<T> Members
public IEnumerator<T> GetEnumerator()
{
return _innerList.Select(x => x.Target).GetEnumerator();
}
#endregion
#region IEnumerable Members
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return this.GetEnumerator();
}
#endregion
public void Purge()
{
_innerList.RemoveAll(wr => !wr.IsAlive);
}
}
इस वर्ग के निम्नलिखित वर्गों और विस्तार तरीकों का उपयोग करता:
यहां नमूने के कार्यान्वयन है IndexOf
,
public static int IndexOf<T>(this IEnumerable<T> source, T item)
{
var entry = source.Select((x, i) => new { Value = x, Index = i })
.Where(x => object.Equals(x.Value, item))
.FirstOrDefault();
return entry != null ? entry.Index : -1;
}
CopyTo
(IList<T>.IndexOf
के रूप में ही है, लेकिन एक IEnumerable<T>
पर काम करता है) (IList<T>.CopyTo
के रूप में ही है, लेकिन एक IEnumerable<T>
पर काम करता है)
public static void CopyTo<T>(this IEnumerable<T> source, T[] array, int startIndex)
{
int lowerBound = array.GetLowerBound(0);
int upperBound = array.GetUpperBound(0);
if (startIndex < lowerBound)
throw new ArgumentOutOfRangeException("startIndex", "The start index must be greater than or equal to the array lower bound");
if (startIndex > upperBound)
throw new ArgumentOutOfRangeException("startIndex", "The start index must be less than or equal to the array upper bound");
int i = 0;
foreach (var item in source)
{
if (startIndex + i > upperBound)
throw new ArgumentException("The array capacity is insufficient to copy all items from the source sequence");
array[startIndex + i] = item;
i++;
}
}
दो जवाब को देखने के लिए अब तक दोनों कुछ नहीं-पूरी तरह से स्वचालित पर्ज कदम है दिलचस्प। मुझे इसके बारे में सोचने में कुछ समय बिताना होगा, लेकिन वास्तव में यह पूरी तरह से स्वचालित नहीं हो सकता है, भले ही यह पूरी तरह से स्वचालित हो। –
पर्जिंग गणना के दौरान सबसे स्वाभाविक रूप से किया जाता है। एकमात्र अन्य विकल्प एक आवधिक शुद्धीकरण होना है, इस स्थिति में समाधान "कमजोर सूची" की तुलना में "कैश" से अधिक हो जाता है। कैशिंग के लिए 'वीक रेफरेंस' का उपयोग नहीं किया जाना चाहिए; इसके लिए बेहतर समाधान हैं (उदा।, [System.Runtime.Caching] (http://msdn.microsoft.com/en-us/library/system.runtime.caching.aspx))। –
System.Runtime.Caching के बारे में दिलचस्प सुझाव के लिए धन्यवाद। लेकिन मेरे पास इस प्रश्न के लिए एक विशेष अनुप्रयोग था, और मैं कुछ बाधाओं को देख सकता हूं - 1) मुझे वस्तुओं को पाने के लिए स्ट्रिंग कुंजियों का उपयोग करने की आवश्यकता नहीं है या नहीं, मैं सिर्फ मांग पर उन्हें फिर से स्थापित करने में सक्षम होना चाहता हूं।2) यदि संभवतः कचरा होने के कारण वस्तुओं को कैश छोड़ दिया जाता है, तो मैं शायद अधिक खुश रहूंगा, न कि अन्य विविध कारणों (जैसे कैश बहुत अधिक मेमोरी का उपयोग करके)। –