1. 起源
此问题源于[秋风人事档案管理类别]用Delphi XE重编译中所发现。
快十年了,当初Delphi 7所编写项目,想用Delphi
XE重新编译,并打算做为Free软件发表,编译错误中发现此问题,感觉颇有些意思,遂记录下来,以做备忘。
自Delphi 2009之后,转做c#之WinForm界面开发,Delphi
2010自此未实际做过项目,因而至此才境遇此题材。
此时Delphi
XE快快已至XE10版。因情结而不愿XE2之后的use方法,遂决定以Delphi
XE做为工具,重整老项目。
而此题材,简单来讲,就是当记录体(record)做为属性出现时,其赋值问题。
2. 赋值
诸如,我有一笔录体属性如下(这里以TPoint表明问题,实际项目中为自定义记录体):
type
TForm1 = class(TForm)
btnTest: TButton;
procedure btnTestClick(Sender: TObject);
private
{ Private declarations }
FPoint: TPoint;
public
{ Public declarations }
property Point: TPoint read FPoint write FPoint;
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.btnTestClick(Sender: TObject);
begin
//Point.X := 12; //如此赋值不成功,报错为Left side cannot be assigned to
//Point.Y := 12;
with Point do
begin
X := 12;
Y := 12;
end;
ShowMessage(Format('x: %d, y: %d', [Point.X, Point.Y]));
end;
直白赋于做为属性的record值,比如Point.X :=
12,编译都不可能因此。大家得以理解为面向对象封装问题不容许操作其内部数据,因为记录体为值类型。
人事档案,但事有折中,借with语句,即可方便赋值。所以在昔日项目中,多用此写法,简洁而便宜,而这种写法在Delphi
2009及往日版本,都帮忙,可能是Delphi编译器的BUG吧!
假使是,我爱不释手这些BUG,它简洁了我的写法,特别是性质有多重嵌套时。
3. 不再帮助
Delphi命运多舛,像个不可能决定自己命局的闺女一样被卖来卖去。工作缘故换了开发工具,十多年的Delphi开发从此搁置,不曾想其间多少变化,如今再用,细微变化已别于昔时。
如上面代码,用with语句赋值,也不算了,报错为[DCC Error] Unit1.pas(34): E2064 Left side
cannot be assigned to.
baidu看有没有人接近疑惑?可能国内用Delphi渐少原因呢,竟没找到类似问题,于是stackoverflow一下,果然碰着一根筋的同伙:
Left side cannot be assigned for a record
type
Delphi 2010+ and “Left side cannot be assigned to” in read-only
records: can this be
disabled?
看诸回复,大意是Delphi
2010及今后版本其编译器检查比原先更为严谨,其中还有人致谢这么更改。研究相比较强烈,说吗的都有。日!
与提问者一样,我只想大概地做为属性以记录需的的数额,仅此而已。那是一个一心可行的言语特色,就如此给干了,这是历史的滞后!
4. 化解方法
这条路关闭了,总还有任何路,是不是?编译器想必正是处理属性为Get、Set形式,而加以特别处理?
小结下啊!假诺还想用此方法,就折中下:
a. 直接换属性为字段,即
property Point: TPoint read FPoint write FPoint;
换为Point: TPoint;
这条措施违背于面向对象封装,不佳,但能用。
b. 假如自定义record,可换为class,这思路中。
c. 以指针形式去赋值:
procedure TForm1.btnTestClick(Sender: TObject);
begin
with PPoint(@Point)^ do
begin
X := 12;
Y := 12;
end;
ShowMessage(Format('x: %d, y: %d', [Point.X, Point.Y]));
end;
自我个人倾向于这多少个。自定义记录体,再定义个指向它的指针结构,就可以了。
d. 以临时变量代之,反赋回去:
procedure TForm1.btnTestClick(Sender: TObject);
var
p: TPoint;
begin
with p do
begin
X := 12;
Y := 12;
end;
Point := p;
ShowMessage(Format('x: %d, y: %d', [Point.X, Point.Y]));
end;
这应该是明媒正娶写法,但总感到繁琐令人不快。
左右是少了前头版本这自然淋漓简洁随意的写法,蛋疼之极也!