public Cache(Func <T, R> function, int maxCapacity, bool cacheError)
                {
                    _function = args =>
                    {
                        var weakArgs = WeakReferenceExtensions.Create(args);

#if DEBUG
                        var invokeDuration = default(TimeSpan);
                        Interlocked.Increment(ref _invocationCount);
#endif
                        Trim();

                        var res = default(ILruCacheEntry <WeakReference <T>, R>);
                        try
                        {
#if DEBUG
                            var swInvoke = Stopwatch.StartNew();
#endif
                            var value = function(args);
#if DEBUG
                            invokeDuration = swInvoke.Elapsed;
#endif
                            res = new LruValueCacheEntry <WeakReference <T>, R>(weakArgs, value);
                        }
                        catch (Exception ex) when(_cacheError)
                        {
                            res = new LruErrorCacheEntry <WeakReference <T>, R>(weakArgs, ex);
                        }

                        Interlocked.Increment(ref _count);
#if DEBUG
                        res.GetMetrics().InvokeDuration = invokeDuration;
#endif
                        return(res);
                    };

                    _cache       = new WeakCacheDictionary <T, ILruCacheEntry <WeakReference <T>, R> >();
                    _lock        = new ReaderWriterLockSlim(LockRecursionPolicy.NoRecursion);
                    _maxCapacity = maxCapacity;
                    _cacheError  = cacheError;
                }
                public Cache(Func <T, R> function, int maxCapacity, IEqualityComparer <T> comparer, bool cacheError)
                {
                    _function = args =>
                    {
#if DEBUG
                        var invokeDuration = default(TimeSpan);
                        _invocationCount++;
#endif
                        Trim();

                        var res = default(ILruCacheEntry <T, R>);
                        try
                        {
#if DEBUG
                            var swInvoke = Stopwatch.StartNew();
#endif
                            var value = function(args);
#if DEBUG
                            invokeDuration = swInvoke.Elapsed;
#endif
                            res = new LruValueCacheEntry <T, R>(args, value);
                        }
                        catch (Exception ex) when(_cacheError)
                        {
                            res = new LruErrorCacheEntry <T, R>(args, ex);
                        }
#if DEBUG
                        res.GetMetrics().InvokeDuration = invokeDuration;
#endif
                        return(res);
                    };

                    _cache       = new CacheDictionary <T, ILruCacheEntry <T, R> >(comparer);
                    _maxCapacity = maxCapacity;
                    _cacheError  = cacheError;
                }