using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Lifetime
{
    // Listing 7-3
    public class WeakCache<TKey, TValue> where TValue : class
    {
        private Dictionary<TKey, WeakReference<TValue>> _cache =
            new Dictionary<TKey, WeakReference<TValue>>();

        public void Add(TKey key, TValue value)
        {
            _cache.Add(key, new WeakReference<TValue>(value));
        }

        public bool TryGetValue(TKey key, out TValue cachedItem)
        {
            WeakReference<TValue> entry;
            if (_cache.TryGetValue(key, out entry))
            {
                bool isAlive = entry.TryGetTarget(out cachedItem);
                if (!isAlive)
                {
                    _cache.Remove(key);
                }
                return isAlive;
            }
            else
            {
                cachedItem = null;
                return false;
            }
        }
    }

    class Examples3_4
    {
        public static void UseWeakCache()
        {
            // Listing 7-4
            var cache = new WeakCache<string, byte[]>();

            var data = new byte[100];
            cache.Add("d", data);

            byte[] fromCache;
            Console.WriteLine("Pobieranie: " + cache.TryGetValue("d", out fromCache));
            Console.WriteLine("Ta sama referencja?  " + object.ReferenceEquals(data, fromCache));
            fromCache = null;

            GC.Collect();
            Console.WriteLine("Pobieranie: " + cache.TryGetValue("d", out fromCache));
            Console.WriteLine("Ta sama referencja?  " + object.ReferenceEquals(data, fromCache));
            fromCache = null;

            data = null;
            GC.Collect();
            Console.WriteLine("Pobieranie: " + cache.TryGetValue("d", out fromCache));
            Console.WriteLine("Czy null?  " + (fromCache == null));

        }
    }
}
