/// <summary>
        /// Determine if the binary expression is comparing the key value against a constant
        /// using CompareTo.
        /// </summary>
        /// <param name="expression">The expression.</param>
        /// <param name="keyMemberInfo">The name of the parameter key.</param>
        /// <param name="value">Returns the constant being compared against.</param>
        /// <param name="expressionType">Returns the type of the comparison.</param>
        /// <returns>True if this expression is comparing the key value against a constant.</returns>
        private static bool IsCompareToExpression(BinaryExpression expression, MemberInfo keyMemberInfo, out TKey value, out ExpressionType expressionType)
        {
            // CompareTo is only guaranteed to return <0, 0 or >0 so allowing for
            // comparisons with values other than 0 is complicated/subtle.
            // One way this could be expanded is by recognizing "< 1", and "> -1" as well.
            if (IsCompareTo(expression.Left, keyMemberInfo, out value))
            {
                int comparison;
                if (ConstantExpressionEvaluator <int> .TryGetConstantExpression(expression.Right, out comparison) &&
                    0 == comparison)
                {
                    expressionType = expression.NodeType;

                    return(true);
                }
            }

            if (IsCompareTo(expression.Right, keyMemberInfo, out value))
            {
                int comparison;
                if (ConstantExpressionEvaluator <int> .TryGetConstantExpression(expression.Left, out comparison) &&
                    0 == comparison)
                {
                    expressionType = GetReverseExpressionType(expression.NodeType);

                    return(true);
                }
            }

            expressionType = ExpressionType.Equal;
            value          = default(TKey);
            return(false);
        }
        /// <summary>
        /// Determine if the binary expression is comparing the key value against a string
        /// using the simplest (two-argument) form of String.Compare.
        /// </summary>
        /// <param name="expression">The expression.</param>
        /// <param name="keyMemberInfo">The name of the parameter key.</param>
        /// <param name="value">Returns the constant being compared against.</param>
        /// <param name="expressionType">Returns the type of the comparison.</param>
        /// <returns>True if this expression is comparing the key value against a constant string.</returns>
        private static bool IsStringComparisonExpression(BinaryExpression expression, MemberInfo keyMemberInfo, out TKey value, out ExpressionType expressionType)
        {
            Debug.Assert(typeof(string) == typeof(TKey), "This method should only be called for string keys");

            // CompareTo is only guaranteed to return <0, 0 or >0 so allowing for
            // comparisons with values other than 0 is complicated/subtle.
            // One way this could be expanded is by recognizing "< 1", and "> -1" as well.
            //
            // This code is tricky because there are 4 possibilities and we want
            // to turn them into a canonical form. In the first two cases we do
            // not reverse the sense of the comparison:
            //   1. String.Compare(Key, "m") < 0
            //   2. 0 < String.Compare("m", Key)
            // In the second two cases we do reverse the sense of the comparison:
            //   3. String.Compare("m", Key) > 0
            //   4. 0 > String.Compare(Key, "m")
            if (IsStringCompare(expression.Left, keyMemberInfo, out value))
            {
                int comparison;
                if (ConstantExpressionEvaluator <int> .TryGetConstantExpression(expression.Right, out comparison) && 0 == comparison)
                {
                    expressionType = expression.NodeType;
                    return(true);
                }
            }
            else if (IsStringCompareReversed(expression.Right, keyMemberInfo, out value))
            {
                int comparison;
                if (ConstantExpressionEvaluator <int> .TryGetConstantExpression(expression.Left, out comparison) && 0 == comparison)
                {
                    expressionType = expression.NodeType;
                    return(true);
                }
            }
            else if (IsStringCompareReversed(expression.Left, keyMemberInfo, out value))
            {
                int comparison;
                if (ConstantExpressionEvaluator <int> .TryGetConstantExpression(expression.Right, out comparison) && 0 == comparison)
                {
                    expressionType = GetReverseExpressionType(expression.NodeType);
                    return(true);
                }
            }
            else if (IsStringCompare(expression.Right, keyMemberInfo, out value))
            {
                int comparison;
                if (ConstantExpressionEvaluator <int> .TryGetConstantExpression(expression.Left, out comparison) && 0 == comparison)
                {
                    expressionType = GetReverseExpressionType(expression.NodeType);
                    return(true);
                }
            }

            expressionType = ExpressionType.Equal;
            value          = default(TKey);
            return(false);
        }
        /// <summary>
        /// Determine if the MethodCallExpression is a key comparison method, and
        /// return the index range if it is.
        /// </summary>
        /// <param name="methodCall">The method call expression.</param>
        /// <param name="keyMemberInfo">The name of the parameter member that is the key.</param>
        /// <param name="keyRange">Returns the key range if this is a key comparison method.</param>
        /// <returns>True if the method is a key comparison method.</returns>
        private static bool IsComparisonMethod(MethodCallExpression methodCall, MemberInfo keyMemberInfo, out KeyRange <TKey> keyRange)
        {
            if (null != methodCall.Object && IsKeyAccess(methodCall.Object, keyMemberInfo))
            {
                TKey value;

                // TKey.Equals
                if ((equalsMethod == methodCall.Method) &&
                    ConstantExpressionEvaluator <TKey> .TryGetConstantExpression(methodCall.Arguments[0], out value))
                {
                    keyRange = new KeyRange <TKey>(Key <TKey> .CreateKey(value, true), Key <TKey> .CreateKey(value, true));
                    return(true);
                }
            }

            if (typeof(TKey) == typeof(string))
            {
                if (null != methodCall.Object &&
                    IsKeyAccess(methodCall.Object, keyMemberInfo))
                {
                    TKey value;

                    // String.StartsWith
                    if (StringExpressionEvaluatorHelper.StringStartWithMethod == methodCall.Method &&
                        ConstantExpressionEvaluator <TKey> .TryGetConstantExpression(methodCall.Arguments[0], out value))
                    {
                        // Lower range is just the string, upper range is the prefix
                        keyRange = new KeyRange <TKey>(Key <TKey> .CreateKey(value, true), Key <TKey> .CreatePrefixKey(value));
                        return(true);
                    }
                }
                else if (null == methodCall.Object)
                {
                    // Static String.Equals
                    if (StringExpressionEvaluatorHelper.StringStaticEqualsMethod == methodCall.Method)
                    {
                        TKey value;
                        if ((IsKeyAccess(methodCall.Arguments[0], keyMemberInfo) &&
                             ConstantExpressionEvaluator <TKey> .TryGetConstantExpression(methodCall.Arguments[1], out value)) ||
                            (IsKeyAccess(methodCall.Arguments[1], keyMemberInfo) &&
                             ConstantExpressionEvaluator <TKey> .TryGetConstantExpression(methodCall.Arguments[0], out value)))
                        {
                            keyRange = new KeyRange <TKey>(Key <TKey> .CreateKey(value, true), Key <TKey> .CreateKey(value, true));
                            return(true);
                        }
                    }
                }
            }

            keyRange = null;
            return(false);
        }
        /// <summary>
        /// Determine if the expression is a call to String.Compare(value, key).
        /// </summary>
        /// <param name="expression">The expression to examine.</param>
        /// <param name="keyMemberInfo">The name of the key member.</param>
        /// <param name="value">Returns the string value being compared against.</param>
        /// <returns>
        /// True if the expression is a call to String.Compare(value, key).
        /// </returns>
        private static bool IsStringCompareReversed(Expression expression, MemberInfo keyMemberInfo, out TKey value)
        {
            if (expression is MethodCallExpression)
            {
                MethodCallExpression methodCall = (MethodCallExpression)expression;
                if (methodCall.Method == StringExpressionEvaluatorHelper.StringStaticCompareMethod &&
                    IsKeyAccess(methodCall.Arguments[1], keyMemberInfo))
                {
                    return(ConstantExpressionEvaluator <TKey> .TryGetConstantExpression(methodCall.Arguments[0], out value));
                }
            }

            value = default(TKey);
            return(false);
        }
        /// <summary>
        /// Determine if the expression is a call to [param].[member].CompareTo(value).
        /// </summary>
        /// <param name="expression">The expression to examine.</param>
        /// <param name="keyMemberInfo">The name of the key member.</param>
        /// <param name="value">Returns the string value being compared against.</param>
        /// <returns>
        /// True if the expression is a call to parameter.keyMember.CompareTo(value).
        /// </returns>
        private static bool IsCompareTo(Expression expression, MemberInfo keyMemberInfo, out TKey value)
        {
            if (expression is MethodCallExpression)
            {
                MethodCallExpression methodCall = (MethodCallExpression)expression;
                if (methodCall.Method == compareToMethod &&
                    null != methodCall.Object &&
                    IsKeyAccess(methodCall.Object, keyMemberInfo))
                {
                    return(ConstantExpressionEvaluator <TKey> .TryGetConstantExpression(methodCall.Arguments[0], out value));
                }
            }

            value = default(TKey);
            return(false);
        }
        /// <summary>
        /// Determine if the binary expression is comparing the key value against a constant.
        /// </summary>
        /// <param name="expression">The expression.</param>
        /// <param name="keyMemberInfo">The name of the parameter key.</param>
        /// <param name="value">Returns the constant being compared against.</param>
        /// <param name="expressionType">Returns the type of the comparison.</param>
        /// <returns>True if this expression is comparing the key value against a constant.</returns>
        private static bool IsSimpleComparisonExpression(BinaryExpression expression, MemberInfo keyMemberInfo, out TKey value, out ExpressionType expressionType)
        {
            if (IsKeyAccess(expression.Left, keyMemberInfo) &&
                ConstantExpressionEvaluator <TKey> .TryGetConstantExpression(expression.Right, out value))
            {
                expressionType = expression.NodeType;
                return(true);
            }

            if (IsKeyAccess(expression.Right, keyMemberInfo) &&
                ConstantExpressionEvaluator <TKey> .TryGetConstantExpression(expression.Left, out value))
            {
                // The access is on the right so we have to switch the comparison type
                expressionType = GetReverseExpressionType(expression.NodeType);
                return(true);
            }

            expressionType = ExpressionType.Equal;
            value          = default(TKey);
            return(false);
        }