Vergleichsoperationen implementieren
Nach oben zu Eine Klasse zur Aktivierung des selbstdefinierten Variant-Typs erzeugen
Es gibt zwei Möglichkeiten, einem selbstdefinierten Variant-Typ Vergleichsoperationen (=, <>, <, <=, >, >=) zu ermöglichen. Sie können entweder die Methode Compare
oder die Methode CompareOp
überschreiben.
Die Methode Compare ist einfacher, wenn Ihr selbstdefinierter Variant-Typ sämtliche Vergleichsoperatoren unterstützt. Diese Methode nimmt drei Parameter entgegen: den linken und rechten Operanden sowie einen var-Parameter, der das Vergleichsergebnis zurückgibt.
TConvertVariantType
aus der Unit VarConv implementiert z.B. die folgende Compare
-Methode:
Delphi:
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
// unterstützt...
// convvar cmp zahl
// Vergleicht den Wert von convvar und zahl
// convvar1 cmp convvar2
// Vergleich nach Umwandlung von convvar2 in den Unit-Typ von convvar1
// Der rechte Operand kann auch ein String sein. Enthält der String Unit-Informationen,
// wird er wie eine varConvert behandelt, sonst wie ein 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;
Unterstützt der selbstdefinierte Typ nicht die Vergleichsarten "größer als" oder "kleiner als", sondern nur "gleich" und "ungleich", ist es schwierig, die Methode Compare
zu implementieren, weil sie crLessThan
, crEqual
oder crGreaterThan
zurückgeben muss. Bei "ungleich" als einzig möglicher Antwort ist jedoch nicht zu bestimmen, ob crLessThan
oder crGreaterThan
als Rückgabewert in Frage kommt.
In diesem Fall muss statt der Methode Compare die Methode CompareOp überschrieben werden.
CompareOp besitzt drei Parameter: den Wert des linken Operanden, den Wert des rechten Operanden sowie den Vergleichsoperator. Implementieren Sie diese Methode zur Ausführung der Operation und geben Sie einen Booleschen Wert zurück, wenn der Vergleich True
ergibt. Ergibt der Vergleich keinen Sinn, rufen Sie anschließend die Methode RaiseInvalidOp auf.
Die folgende CompareOp
-Methode entstammt z.B. dem TComplexVariantType
-Objekt aus der Unit System.VarCmplx. Sie unterstützt nur die Prüfung auf Gleichheit oder Ungleichheit.
Delphi:
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;
Beachten Sie, dass diese beiden Implementierungen nur eine sehr begrenzte Anzahl von Typen als Operanden unterstützen. Wie bei binären Operationen können Sie auch hier die Methoden RightPromotion
und LeftPromotion
verwenden, um die Anzahl der zu berücksichtigenden Fälle zu beschränken, indem Sie eine Umwandlung erzwingen, bevor Compare
oder CompareOp
aufgerufen wird.