RAD Studio |  |

Implementing Comparison Operations
See Also
Collapse All

There are two ways to enable a custom variant type to support comparison operators (=, <>, <, <=, >, >=). You can override the Compare method, or you can override the CompareOp method.

The Compare method is easiest if your custom variant type supports the full range of comparison operators. Compare takes three parameters: the left-hand operand, the right-hand operand, and a var Parameter that returns the relationship between the two. For example, the TConvertVariantType object in the VarConv unit implements the following Compare method:

Copy Code

    procedure TConvertVariantType.Compare(const Left, Right: TVarData;
    var Relationship: TVarCompareResult);
    const
    CRelationshipToRelationship: array [TValueRelationship] of TVarCompareResult =
    (crLessThan, crEqual, crGreaterThan);
    var
    LValue: Double;
    LType: TConvType;
    LRelationship: TValueRelationship;
    begin
    // supports...
    //   convvar cmp number
    //     Compare the value of convvar and the given number
      //   convvar1 cmp convvar2
    //     Compare after converting convvar2 to convvar1's unit type
      //  The right can also be a string.  If the string has unit info then it is
    //    treated like a varConvert else it is treated as a double
    LRelationship := EqualsValue;
    case Right.VType of
        varString:
          if TryStrToConvUnit(Variant(Right), LValue, LType) then
            if LType = CIllegalConvType then
              LRelationship := CompareValue(TConvertVarData(Left).VValue, LValue)
            else
              LRelationship := ConvUnitCompareValue(TConvertVarData(Left).VValue,
                                                 TConvertVarData(Left).VConvType, LValue, LType)
            else
              RaiseCastError;
        varDouble:
          LRelationship := CompareValue(TConvertVarData(Left).VValue, TVarData(Right).VDouble);
        else
          if Left.VType = VarType then
            LRelationship := ConvUnitCompareValue(TConvertVarData(Left).VValue,
                               TConvertVarData(Left).VConvType, TConvertVarData(Right).VValue,
                               TConvertVarData(Right).VConvType)
          else
            RaiseInvalidOp;
      end;
      Relationship := CRelationshipToRelationship[LRelationship];
    end;

If the custom type does not support the concept of "greater than" or "less than," only "equal" or "not equal," however, it is difficult to implement the Compare method, because Compare must return crLessThan, crEqual, or crGreaterThan. When the only valid response is "not equal," it is impossible to know whether to return crLessThan or crGreaterThan. Thus, for types that do not support the concept of ordering, you can override the CompareOp method instead.

CompareOp has three parameters: the value of the left-hand operand, the value of the right-hand operand, and the comparison operator. Implement this method to perform the operation and return a boolean that indicates whether the comparison is True. You can then call the RaiseInvalidOp method when the comparison makes no sense.

For example, the following CompareOp method comes from the TComplexVariantType object in the VarCmplx unit. It supports only a test of equality or inequality:

Copy Code

    function TComplexVariantType.CompareOp(const Left, Right: TVarData;
    const Operator: Integer): Boolean;
    begin
    Result := False;
    if (Left.VType = VarType) and (Right.VType = VarType) then
    case Operator of
    opCmpEQ:
    Result := TComplexVarData(Left).VComplex.Equal(TComplexVarData(Right).VComplex);
    opCmpNE:
    Result := not TComplexVarData(Left).VComplex.Equal(TComplexVarData(Right).VComplex);
    else
    RaiseInvalidOp;
    end
    else
    RaiseInvalidOp;
    end;

Note that the types of operands that both these implementations support are very limited. As with binary operations, you can use the RightPromotion and LeftPromotion methods to limit the cases you must consider by forcing a cast before Compare or CompareOp is called.

See Also

Implementing Binary Operations

Implementing Unary Operations

Enabling Casting

Copying and Clearing Custom Variants

Using the TCustomVariantType Descendant

Loading and Saving Custom Variant Values

Copyright(C) 2009 Embarcadero Technologies, Inc. All Rights Reserved.
What do you think about this topic? Send feedback!