private static Func <TIn, TOut> CompileFromFingerprint(Expression <Func <TIn, TOut> > expr)
            {
                List <object> capturedConstants;
                ExpressionFingerprintChain fingerprint = FingerprintingExpressionVisitor.GetFingerprintChain(expr, out capturedConstants);

                if (fingerprint != null)
                {
                    var del = _fingerprintedCache.GetOrAdd(fingerprint, _ => {
                        // Fingerprinting succeeded, but there was a cache miss. Rewrite the expression
                        // and add the rewritten expression to the cache.

                        var hoistedExpr = HoistingExpressionVisitor <TIn, TOut> .Hoist(expr);
                        return(hoistedExpr.Compile());
                    });
                    return(model => del(model, capturedConstants));
                }

                // couldn't be fingerprinted
                return(null);
            }
        // Returns the fingerprint chain + captured constants list for this expression, or null
        // if the expression couldn't be fingerprinted.
        public static ExpressionFingerprintChain GetFingerprintChain(
            Expression expr,
            out List <object> capturedConstants
            )
        {
            FingerprintingExpressionVisitor visitor = new FingerprintingExpressionVisitor();

            visitor.Visit(expr);

            if (visitor._gaveUp)
            {
                capturedConstants = null;
                return(null);
            }
            else
            {
                capturedConstants = visitor._seenConstants;
                return(visitor._currentChain);
            }
        }