2

I would like to have expression classes that compare two objects and pass the below test.

public abstract class ComparisonExpression
{
    public bool Evaluate(IComparable left, object right)
    {
        if (left == null && right == null)
            return true;

        if (left == null || right == null)
            return false;

        return GetResult(left.CompareTo(right));
    }

    protected abstract bool GetResult(int comparisonResult);
}

public class AreEqualExpression : ComparisonExpression
{
    protected override bool GetResult(int comparisonResult)
    {
        return comparisonResult == 0;
    }
}

// TEST

const int i = 123;
const long l = 123L;
const string s = "123";

Assert.IsTrue(new AreEqualExpression().Evaluate(i, l));
Assert.IsFalse(new AreEqualExpression().Evaluate(i, s));
Assert.IsFalse(new AreEqualExpression().Evaluate(l, s));

It seems like IComparable implementation expects the given type matches the current type. I am having an exception like "Object must be of type Int32.".

I thought returning false if types are not equal. It prevents the exception but it brakes the behavior that i want.

Also I thought about a type conversion but this time string and int comparison will return true, which i do not want.

Any suggestions?

4

1 回答 1

0

如果你定义了这个助手类

public static class NumericalHelper {
    public static double AsDouble(this object value, out bool success) {
        if (value is sbyte || value is byte || value is short || value is ushort || value is int || value is uint || value is long || value is decimal || value is ulong || value is float || value is double || value.GetType().IsEnum) {
            success = true;
            return Convert.ToDouble(value);
        }
        success = false;
        return 0;
    }
}

您可以像这样进行比较:

public bool Evaluate(IComparable left, object right) {
    if (left == null && right == null)
        return true;

    if (left == null || right == null)
        return false;

    bool isNumerical;
    double leftValue = left.AsDouble(out isNumerical);
    double rightValue = isNumerical ? right.AsDouble(out isNumerical) : 0;

    if (isNumerical)
        return GetResult(Comparer<Double>.Default.Compare(leftValue, rightValue));
    else {
        if (left.GetType() == right.GetType())
            return GetResult(left.CompareTo(right));
        else
            return false;
}

但请注意,通常将相等性与Equals方法或IEquatable接口进行比较,在您的示例中根本没有考虑。这是有关实施平等的更多信息。这对我来说似乎是一个问题,这不适合使用当前的类设计。

于 2017-03-14T23:10:20.313 回答