Delphi中记录体做为属性的赋值方法
2018-06-17 18:56:57来源:未知 阅读 ()
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 “E2064 Left side cannot be assigned to” error appeared when upgrading a project from 2009 to XE
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;
这应该是正统写法,但总感觉繁琐令人难受。
反正是少了之前版本那洒脱淋漓简洁随意的写法,蛋疼之极也!
标签:
版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有
- Delphi10.3的ListView学习(大图标) 2020-06-05
- Delphi10.3的SpeedButton/BitBtn学习 2020-06-05
- Delphi10.3状态栏上显示进度条/图片 2020-06-02
- Delphi10.3下自带系统托盘 TrayIcon的使用 2020-06-01
- delphi10.3安装使用mySQL 2020-05-31
IDC资讯: 主机资讯 注册资讯 托管资讯 vps资讯 网站建设
网站运营: 建站经验 策划盈利 搜索优化 网站推广 免费资源
网络编程: Asp.Net编程 Asp编程 Php编程 Xml编程 Access Mssql Mysql 其它
服务器技术: Web服务器 Ftp服务器 Mail服务器 Dns服务器 安全防护
软件技巧: 其它软件 Word Excel Powerpoint Ghost Vista QQ空间 QQ FlashGet 迅雷
网页制作: FrontPages Dreamweaver Javascript css photoshop fireworks Flash