弱引用与弱委托

来源:互联网 发布:win7 64位纯净版 知乎 编辑:程序博客网 时间:2024/04/29 01:37

一、弱引用:

  我们设计全局缓存时,使用静态或全局字段来引用某个对象,做到一次创建多次使用。比如:

    class Program    {        private static DataCache _cache;        public static DataCache Cache        {            get            {                if(_cache == null)                    _cache = new DataCache();                return _cache;            }        }        static void Main(string[] args)        {            byte [] ss = new byte[]{1,2,3};            GC.Collect();            Console.WriteLine("GC执行完毕");            Console.Read();        }    }   class DataCache   {       private IList<string> datas;   }

但这样存在弊端:

  • DataCache没频繁使用时,浪费内存空间。
  • 由于GC只能回收不可达对象,所以没有办法回收这些资源。

WeakReference出场:即在引用对象的同时仍然允许对该对象进行垃圾回收。

所以我们可以这样设计缓存:

class Program    {        static  WeakReference _cache = new WeakReference(null);        public static DataCache Cache        {            get            {                DataCache cache = _cache.Target as DataCache;                if(cache == null)                {                    cache = new DataCache();                    _cache.Target = cache;                }                return cache;            }        }        static void Main(string[] args)        {            byte [] ss = new byte[]{1,2,3};            Cache.Test();            Cache.Test();            GC.Collect();            Console.WriteLine("GC执行完毕");            Cache.Test();            Console.Read();        }    }   class DataCache   {       private IList<string> datas;       ~DataCache()       {           Console.WriteLine("Destory...");        }       public void Test()       {           Console.WriteLine("Test");       }   }

二、弱委托

弱委托解决当委托对象的生命周期足够的长时,导致委托内部持有的强对象不能回收,

比如:

    class Program    {        static void Main(string[] args)        {            Action<string> sAction = new Action<string>(new ClassTest().Print);            sAction("abc");            GC.Collect();            sAction("abc");        }    }    internal class ClassTest    {        public void Print(string s)        {            Console.WriteLine(s);        }    }

输出结果为:abc abc
为了解决当垃圾回收进行时,委托的对象任然存在,就用到了WeakReference

  class Program    {        static void Main(string[] args)        {            Action<string> sAction = new Action<string>(new ClassTest().Print);            WeakReference weakReference = new WeakReference(new ClassTest());            sAction = (s) =>                          {                              object o = weakReference.Target;                              if (o != null)                              {                                  ((ClassTest)o).Print(s);                              }                          };            sAction("def");            GC.Collect();            sAction("def");        }    }    internal class ClassTest    {        public void Print(string s)        {            Console.WriteLine(s);        }    }

输出结果当然只有一个def了。

CLR var C#中的弱委托:

 public abstract class WeakDelegate<TDelegate> where TDelegate : class /* MulticastDelegate */ {        // This lightweight private struct puts a compile-time type-safety wrapper around the non-generic WeakReference class        private struct WeakReference<T> : IDisposable where T : class {            private WeakReference m_weakReference;            public WeakReference(T target) { m_weakReference = new WeakReference(target); }            public T Target { get { return (T)m_weakReference.Target; } }            public void Dispose() { m_weakReference = null; }        }        private WeakReference<TDelegate> m_weakDelegate;        private Action<TDelegate> m_removeDelegateCode;        public WeakDelegate(TDelegate @delegate) {            var md = (MulticastDelegate)(Object)@delegate;            if (md.Target == null)                throw new ArgumentException("There is no reason to make a WeakDelegate to a static method.");            // Save a WeakReference to the delegate            m_weakDelegate = new WeakReference<TDelegate>(@delegate);        }        public Action<TDelegate> RemoveDelegateCode {            set {                // Save the delegate that refers to code that knows how to remove the                 // WeakDelegate object when the non-weak delegate object is GC’d                m_removeDelegateCode = value;            }        }        protected TDelegate GetRealDelegate() {            // If the real delegate hasn't been GC'd yet, just return it            TDelegate realDelegate = m_weakDelegate.Target;            if (realDelegate != null) return realDelegate;            // The real delegate was GC'd, we don't need our WeakReference to it anymore (it can be GC'd)            m_weakDelegate.Dispose();            // Remove the delegate from the chain (if the user told us how)            if (m_removeDelegateCode != null) {                m_removeDelegateCode(GetDelegate());                m_removeDelegateCode = null;  // Let the remove handler delegate be GC'd            }            return null;   // The real delegate was GC'd and can't be called        }        // All derived classes must return a delegate to a private method matching the TDelegate type        public abstract TDelegate GetDelegate();        // Implicit conversion operator to convert a WeakDelegate object to an actual delegate        public static implicit operator TDelegate(WeakDelegate<TDelegate> @delegate) {            return @delegate.GetDelegate();        }    }    // This class provides support for the non-generic EventHandler delegate    public sealed class WeakEventHandler : WeakDelegate<EventHandler> {        public WeakEventHandler(EventHandler @delegate) : base(@delegate) { }        /// <summary>Returns a reference to the non-generic EventHandler delegate</summary>        public override EventHandler GetDelegate() { return Callback; }        // This private method must match the desired delegate’s signature        private void Callback(Object sender, EventArgs e) {            // If the target hasn't been GC'd invoke it            var eh = base.GetRealDelegate();            if (eh != null) eh(sender, e);        }    }    // This WeakDelegate partial class provides support for the generic EventHandler<TEventArgs> delegate    public sealed class WeakEventHandler<TEventArgs> : WeakDelegate<EventHandler<TEventArgs>> where TEventArgs : EventArgs {        public WeakEventHandler(EventHandler<TEventArgs> @delegate) : base(@delegate) { }        /// <summary>Returns a reference to the generic EventHandler<typeparam name="TEventArgs"/> delegate</summary>        public override EventHandler<TEventArgs> GetDelegate() { return Callback; }        private void Callback(Object sender, TEventArgs e) {            // If the target hasn't been GC'd invoke it            var eh = base.GetRealDelegate();            if (eh != null) eh(sender, e);        }    }



 

原创粉丝点击