Jan*_*rts 11 delphi operator-overloading delphi-xe2
在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;
Run Code Online (Sandbox Code Playgroud)
代码无法编译.对于R in S编译器所说的语句:不兼容的类型MyRecord和MyEnum.
如何重载In运算符,MyRecord以便在上面的代码中R in S进行求值True?
要使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;
Run Code Online (Sandbox Code Playgroud)
好吧,你几乎可以做到这一点,但你可能不想这样做。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.
Run Code Online (Sandbox Code Playgroud)
以下内容现在将编译,甚至可以工作:
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;
Run Code Online (Sandbox Code Playgroud)
我相信我们都会同意,它比“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;
Run Code Online (Sandbox Code Playgroud)
因此,正如 Dorin 评论的那样,最好还是使用沉闷、古板的“BoolToStr(R.Value in S)”。当然,除非您按行代码付费。以及修复错误的奖励。