在Delphi XE2中,我试图重载记录上的in
运算符,以允许我检查记录所代表的值是否是集合的一部分。我的代码如下所示:
type
MyEnum = (value1, value2, value3);
MySet = set of MyEnum;
MyRecord = record
Value: MyEnum;
class operator In(const A: MyRecord; B: MySet): Boolean;
end;
class operator MyRecord.In(const A: MyRecord; B: MySet): Boolean;
begin
Result := A.Value in B;
end;
procedure TForm1.Button1Click(Sender: TObject);
var
R: MyRecord;
S: MySet;
begin
R.Value := value1;
S := [value1, value2];
Button1.Caption := BoolToStr(R in S);
end;
代码无法编译。对于语句R in S
,编译器说:不兼容的类型MyRecord
和MyEnum
。
如何在In
上重载MyRecord
运算符,以便R in S
在上面的代码中评估为True
?
答案 0 :(得分:5)
要使in运算符工作,右操作数必须是记录类型,因为它是set运算符而不是二元运算符。在你的情况下,它是左操作数。
以下内容将起作用:
type
MyRecord = record
Value: MyEnum;
class operator In(const A: MyRecord; const B: MySet): Boolean;
end;
MyRecord2 = record
Value: MySet;
class operator In(const A: MyRecord; const B: MyRecord2): Boolean;
class operator In(const A: MyEnum; const B: MyRecord2): Boolean;
end;
class operator MyRecord.In(const A: MyRecord; const B: MySet): Boolean;
begin
Result := A.Value in B;
end;
class operator MyRecord2.In(const A: MyRecord; const B: MyRecord2): Boolean;
begin
Result := A.Value in B.Value;
end;
class operator MyRecord2.In(const A: MyEnum; const B: MyRecord2): Boolean;
begin
Result := A in B.Value;
end;
procedure TForm1.Button1Click(Sender: TObject);
var
R: MyRecord;
R2: MyRecord2;
begin
R.Value := value1;
R2.Value := [value1, value2];
if R in R2 then;
if value1 in R2 then;
end;
答案 1 :(得分:1)
嗯,你可以差不多这样做,但你可能不想这样做。 AFAIK,类操作符只能处理它们所定义的类(或记录),因此代码中的R和S都必须是TMyRecord。通过隐式转换的一些不明智的使用,我们得到以下结果:
unit Unit2;
interface
type
MyEnum = (value1, value2, value3);
MySet = set of MyEnum;
MyRecord = record
Value: MyEnum;
ValueSet: MySet;
class operator Implicit(A: MyEnum): MyRecord;
class operator Implicit(A: MySet): MyRecord;
class operator In (Left,Right:MyRecord): Boolean;
end;
implementation
class operator MyRecord.Implicit(A: MyEnum): MyRecord;
begin
Result.Value := A;
end;
class operator MyRecord.Implicit(A: MySet): MyRecord;
begin
Result.ValueSet := A;
end;
class operator MyRecord.In(Left, Right: MyRecord): Boolean;
begin
Result:= left.Value in Right.ValueSet;
end;
end.
以下内容现在可以完成,甚至可以工作:
procedure TForm1.Button1Click(Sender: TObject);
var
R: MyRecord;
S: MyRecord;
begin
R.Value := value1;
S := [value1,value2,value3];
Button1.Caption := BoolToStr(R In S,true);
end;
其中,我相信大家都会同意,比'BoolToStr(R.Value in S)'更优雅。 但是,以下内容也会编译,但结果错误:
procedure TForm1.Button1Click(Sender: TObject);
var
R: MyRecord;
S: MyRecord;
begin
R.Value := value1;
S := [value1,value2,value3];
Button1.Caption := BoolToStr(S In R,true);
end;
所以,正如Dorin评论的那样,更好的是只有沉闷,沉稳的老'BoolToStr(R.Value in S)'。除非您按行代码付费。修复错误也是一个奖励。