弱引用与弱委托

一、弱引用:

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

    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);
        }
    }



 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值