public static BoundConstantExpression FoldConstantBinaryExpression(
            BindContext context,
            BinaryExpressionSyntax syntax,
            MethodSymbol binaryOperator,
            BoundExpression lhs, BoundExpression rhs)
        {
            // Value type + null comparison which will always be false for == and true for !=
            // This folding is needed for null comparisons in generics to work as expected
            if ((lhs.ValueType.IsValueType && rhs.IsConstant && rhs.ConstantValue.Value == null) ||
                (rhs.ValueType.IsValueType && lhs.IsConstant && lhs.ConstantValue.Value == null))
            {
                if (syntax.OperatorToken.Kind() == SyntaxKind.EqualsEqualsToken)
                {
                    return(new BoundConstantExpression(new ConstantValue <bool>(false),
                                                       context.GetTypeSymbol(typeof(bool)), syntax));
                }

                if (syntax.OperatorToken.Kind() == SyntaxKind.ExclamationEqualsToken)
                {
                    return(new BoundConstantExpression(new ConstantValue <bool>(true),
                                                       context.GetTypeSymbol(typeof(bool)), syntax));
                }
            }

            if (!lhs.IsConstant || !rhs.IsConstant)
            {
                return(null);
            }

            if (binaryOperator == null || (binaryOperator.IsOperator && binaryOperator.IsExtern))
            {
                object foldedValue;
                object lhsValue = lhs.ConstantValue.Value;
                object rhsValue = rhs.ConstantValue.Value;

                switch (syntax.OperatorToken.Kind())
                {
                case SyntaxKind.PlusToken:
                    foldedValue = DynamicInvoke.Add(lhsValue, rhsValue);
                    break;

                case SyntaxKind.MinusToken:
                    foldedValue = DynamicInvoke.Sub(lhsValue, rhsValue);
                    break;

                case SyntaxKind.AsteriskToken:
                    foldedValue = DynamicInvoke.Mul(lhsValue, rhsValue);
                    break;

                case SyntaxKind.SlashToken:
                    foldedValue = DynamicInvoke.Div(lhsValue, rhsValue);
                    break;

                case SyntaxKind.PercentToken:
                    foldedValue = DynamicInvoke.Mod(lhsValue, rhsValue);
                    break;

                case SyntaxKind.LessThanLessThanToken:
                    foldedValue = DynamicInvoke.LSh(lhsValue, rhsValue);
                    break;

                case SyntaxKind.GreaterThanGreaterThanToken:
                    foldedValue = DynamicInvoke.RSh(lhsValue, rhsValue);
                    break;

                case SyntaxKind.CaretToken:
                    foldedValue = DynamicInvoke.Xor(lhsValue, rhsValue);
                    break;

                case SyntaxKind.AmpersandToken:
                case SyntaxKind.AmpersandAmpersandToken:     // When we're dealing with constants short circuiting shouldn't matter
                    foldedValue = DynamicInvoke.BitwiseAnd(lhsValue, rhsValue);
                    break;

                case SyntaxKind.BarToken:
                case SyntaxKind.BarBarToken:
                    foldedValue = DynamicInvoke.BitwiseOr(lhsValue, rhsValue);
                    break;

                case SyntaxKind.GreaterThanToken:
                    foldedValue = DynamicInvoke.GreaterThan(lhsValue, rhsValue);
                    break;

                case SyntaxKind.GreaterThanEqualsToken:
                    foldedValue = DynamicInvoke.GreaterThanOrEquals(lhsValue, rhsValue);
                    break;

                case SyntaxKind.LessThanToken:
                    foldedValue = DynamicInvoke.LessThan(lhsValue, rhsValue);
                    break;

                case SyntaxKind.LessThanOrEqualExpression:
                    foldedValue = DynamicInvoke.LessThanOrEquals(lhsValue, rhsValue);
                    break;

                case SyntaxKind.EqualsEqualsToken:
                    foldedValue = DynamicInvoke.Equal(lhsValue, rhsValue);
                    break;

                case SyntaxKind.ExclamationEqualsToken:
                    foldedValue = DynamicInvoke.NotEqual(lhsValue, rhsValue);
                    break;

                default:
                    return(null);
                }

                IConstantValue constantValue = (IConstantValue)Activator.CreateInstance(typeof(ConstantValue <>).MakeGenericType(foldedValue.GetType()), foldedValue);

                return(new BoundConstantExpression(constantValue, context.GetTypeSymbol(foldedValue.GetType()), syntax));
            }

            return(null);
        }