public static CodeExpression Clone(CodeExpression originalExpression)
        {
            if (originalExpression == null)
            {
                return(null);
            }

            RuleExpressionInternal ruleExpr = GetExpression(originalExpression);
            CodeExpression         newExpr  = ruleExpr.Clone(originalExpression);

            ConditionHelper.CloneUserData(originalExpression, newExpr);

            return(newExpr);
        }
        private static bool AdjustValueStandard(Type operandType, object operandValue, Type toType, out object converted)
        {
            // assume it's the same for now
            converted = operandValue;

            // check for null
            if (operandValue == null)
            {
                // are we converting to a value type?
                if (toType.IsValueType)
                {
                    // is the conversion to nullable?
                    if (!ConditionHelper.IsNullableValueType(toType))
                    {
                        // value type and null, so no conversion possible
                        string message = string.Format(CultureInfo.CurrentCulture, Messages.CannotCastNullToValueType, RuleDecompiler.DecompileType(toType));
                        throw new InvalidCastException(message);
                    }

                    // here we have a Nullable<T>
                    // however, we may need to call the implicit conversion operator if the types are not compatible
                    converted = Activator.CreateInstance(toType);
                    return(RuleValidation.StandardImplicitConversion(operandType, toType, null, out ValidationError error));
                }

                // not a value type, so null is valid
                return(true);
            }

            // check simple cases
            Type currentType = operandValue.GetType();

            if (currentType == toType)
            {
                return(true);
            }

            // now the fun begins
            // this should handle most class conversions
            if (toType.IsAssignableFrom(currentType))
            {
                return(true);
            }

            // handle the numerics (both implicit and explicit), along with nullable
            // note that if the value was null, it's already handled, so value cannot be nullable
            if ((currentType.IsValueType) && (toType.IsValueType))
            {
                if (currentType.IsEnum)
                {
                    // strip off the enum representation
                    currentType = Enum.GetUnderlyingType(currentType);
                    ArithmeticLiteral literal = ArithmeticLiteral.MakeLiteral(currentType, operandValue);
                    operandValue = literal.Value;
                }

                bool resultNullable = ConditionHelper.IsNullableValueType(toType);
                Type resultType     = (resultNullable) ? Nullable.GetUnderlyingType(toType) : toType;

                if (resultType.IsEnum)
                {
                    // Enum.ToObject may throw if currentType is not type SByte,
                    // Int16, Int32, Int64, Byte, UInt16, UInt32, or UInt64.
                    // So we adjust currentValue to the underlying type (which may throw if out of range)
                    Type underlyingType = Enum.GetUnderlyingType(resultType);
                    if (AdjustValueStandard(currentType, operandValue, underlyingType, out object adjusted))
                    {
                        converted = Enum.ToObject(resultType, adjusted);
                        if (resultNullable)
                        {
                            converted = Activator.CreateInstance(toType, converted);
                        }
                        return(true);
                    }
                }
                else if ((resultType.IsPrimitive) || (resultType == typeof(decimal)))
                {
                    // resultType must be a primitive to continue (not a struct)
                    // (enums and generics handled above)
                    if (currentType == typeof(char))
                    {
                        char c = (char)operandValue;
                        if (resultType == typeof(float))
                        {
                            converted = (float)c;
                        }
                        else if (resultType == typeof(double))
                        {
                            converted = (double)c;
                        }
                        else if (resultType == typeof(decimal))
                        {
                            converted = (decimal)c;
                        }
                        else
                        {
                            converted = ((IConvertible)c).ToType(resultType, CultureInfo.CurrentCulture);
                        }
                        if (resultNullable)
                        {
                            converted = Activator.CreateInstance(toType, converted);
                        }
                        return(true);
                    }
                    else if (currentType == typeof(float))
                    {
                        float f = (float)operandValue;
                        if (resultType == typeof(char))
                        {
                            converted = (char)f;
                        }
                        else
                        {
                            converted = ((IConvertible)f).ToType(resultType, CultureInfo.CurrentCulture);
                        }
                        if (resultNullable)
                        {
                            converted = Activator.CreateInstance(toType, converted);
                        }
                        return(true);
                    }
                    else if (currentType == typeof(double))
                    {
                        double d = (double)operandValue;
                        if (resultType == typeof(char))
                        {
                            converted = (char)d;
                        }
                        else
                        {
                            converted = ((IConvertible)d).ToType(resultType, CultureInfo.CurrentCulture);
                        }
                        if (resultNullable)
                        {
                            converted = Activator.CreateInstance(toType, converted);
                        }
                        return(true);
                    }
                    else if (currentType == typeof(decimal))
                    {
                        decimal d = (decimal)operandValue;
                        if (resultType == typeof(char))
                        {
                            converted = (char)d;
                        }
                        else
                        {
                            converted = ((IConvertible)d).ToType(resultType, CultureInfo.CurrentCulture);
                        }
                        if (resultNullable)
                        {
                            converted = Activator.CreateInstance(toType, converted);
                        }
                        return(true);
                    }
                    else
                    {
                        if (operandValue is IConvertible convert)
                        {
                            try
                            {
                                converted = convert.ToType(resultType, CultureInfo.CurrentCulture);
                                if (resultNullable)
                                {
                                    converted = Activator.CreateInstance(toType, converted);
                                }
                                return(true);
                            }
                            catch (InvalidCastException)
                            {
                                // not IConvertable, so can't do it
                                return(false);
                            }
                        }
                    }
                }
            }

            // no luck with standard conversions, so no conversion done
            return(false);
        }