Delphi中记录体做为属性的赋值方法
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 := ;
Y := ;
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 := ;
Y := ;
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 := ;
Y := ;
end;
Point := p;
ShowMessage(Format('x: %d, y: %d', [Point.X, Point.Y]));
end;
这应该是正统写法,但总感觉繁琐令人难受。
反正是少了之前版本那洒脱淋漓简洁随意的写法,蛋疼之极也!
Delphi中记录体做为属性的赋值方法的更多相关文章
- DELPHI中枚举类型数据的介绍和使用方法
在看delphi程序的时候看到aa=(a,b,c,d);这样的东西,还以为是数组,同事说是函数,呵呵,当然这两个都不屑一击,原来这样式子是在声明并付值一个枚举类型的数据.下边写下来DELPHI中枚举类 ...
- System中记录体函数命名怪异
//1019unit System; 中发现记录体函数命名怪异//乍一看,很怪异,其实是结构体里面 的变量后面直接写 函数类型了.不像传统先定义T***Event = procedure(S ...
- OC中结构体作为对象属性
在OC中结构体有时候也作为对象的属性 类的定义 #import <Foundation/Foundation.h> typedef struct{ int year; int month; ...
- DELPHI中的消息处理机制(三种消息处理方法的比较,如何截断消息)
DELPHI中的消息处理机制 Delphi是Borland公司提供的一种全新的WINDOWS编程开发工具.由于它采用了具有弹性的和可重用的面向对象Pascal(object-orientedpasca ...
- Delphi中统一显示表格字段名的高效方法
问题描述:在开发数据库程序时,我们经常要使用很多的表格显示组件DBGrid.当DBGrid显示某表格的数据时,其字段标题默认的就是后台数据库中的表格的字段名称.而为了数据库开发方便,后台数据库中的表格 ...
- map中结构体做关键字的注意事项
序: 今天做一道题,由于递归函数比较恶心,如果用记忆化搜索,数据范围极大却又用不全(二维数组存的话直接炸).所以决定干脆使用stl::map存储(反正有O2优化),但是执行insert的时候,编译器却 ...
- Delphi 中记录类型 给记录指针赋值。
PPersion=^TPersion; TPersion=packed record Name:string; Sex:string; Clasee:string; end ...
- Delphi 中记录类型 给记录指针赋值
PPersion=^TPersion; TPersion=packed record Name:string; Sex:string; Clasee:string; end; var persion: ...
- jquery中选择块并改变属性值的方法
本文为大家介绍下使用jquery改变class属性的值,通过removeClass.addClass实现,具体如下,感兴趣的朋友可以学习下jquery改变class属性的值 $("#top_ ...
随机推荐
- English-旅游英语及情景对话
1.旅游英语:预订机票情景对话及常用句型 目前,越来越多的人都选择以飞机为出行方式.但是如何用一口流利的英语订机票呢?这里我们替你总结了一些情景对话,还有一些常用的句型.大家都来学一学吧~A:Good ...
- 配置maven访问nexus,配置项目pom.xml以发布maven项目到nexus中
maven访问nexus有三种配置方法,分别为: 项目pom.xml,优先级最高: user的settings.xml,优先级中,未在pom.xml中配置repository标签,则使用这个配置: m ...
- List去重问题引出来的hashCode和equals方法
一.List 里面是基本类型的去重问题 import java.util.ArrayList; import java.util.HashSet; import java.util.List; imp ...
- Delphi 泛型详解
http://www.cnblogs.com/jxgxy/category/216671.html
- English Conversation – Checking in at an airport
English Conversation – Checking in at an airport Share Tweet Share Tagged With: Ben Franklin Exercis ...
- curl命令解析
curl命令可以实现http post或者get的请求,是linux下的命令行工具 1.1.直接请求url,打印标准输出 1.2.使用-o参数,可以标准输出到指定的位置 [root@VM-3-10-1 ...
- 小程序:pages/index/index/出现脚本错误或未正确调用Page()
第一次尝试玩小程序,配置好以后报错.pages/index/index/出现脚本错误或未正确调用Page() 才发现解决的方式是:新建的文件默认是没有page()的,所以你需要在.js文件中加上Pag ...
- canvas入门笔记
1.Canvas的使用注意 A.要在页面中添加一对canvas标记,默认占300*150的区域 B.我们可以通过html属性‘width’,‘height’来设置canvas的宽高,不可以通过cs ...
- DOM精简版笔记
1.1. 基本概念 1.1.1. DOM DOM Document Object Model 文档对象模型 就是把HTML文档模型化,当作对象来处理 DOM提供的一系列属性和方法可以 ...
- 吴裕雄 python神经网络(6)
import randomimport numpy as npnp.random.randint(0,49,3) ##required libarariesimport tensorflow as t ...