当泛型遇上结构体...
一般使用泛型都是放类啊, 基础类型什么的, 所以使用上和非泛型基本没什么区别, 不过昨天有人在群里问的问题到是暴露了一个特例:
TRC = record Str: string; Int: Integer; end; ... var nRC: TRC; nList: TList<TRC>; i: Integer; begin nList := TList<TRC>.Create; for i := 0 to 9 do begin with nRC do begin Str := IntToStr(i); Int := i; end; nList.Add(nRC); end; nList[3].Str := 'ABC'; {这里会提示左边不允许赋值} nList.Free; end;
显然, 如果不是一个结构体而是一个类型就没问题了, 先不说原因, 这里我先列出思路:
首先编译器不允许赋值, 那么如果是属性呢?
TRC = record private FStr: string; public Int: Integer; property Str: string read FStr write FStr; end;
改成这样...可惜仍然不行, 继续
TRC = record private FStr: string; function GetStr: string; procedure SetStr(const Value: string); public Int: Integer; property Str: string read GetStr write SetStr; end; ... function TRC.GetStr: string; begin Result := FStr; end; procedure TRC.SetStr(const Value: string); begin FStr := Value; end; ... var nRC: TRC; nList: TList<TRC>; i: Integer; begin nList := TList<TRC>.Create; for i := 0 to 9 do begin with nRC do begin Str := IntToStr(i); Int := i; end; nList.Add(nRC); end; ShowMessage(nList[3].Str); nList[3].Str := 'ABC'; ShowMessage(nList[3].Str); nList.Free; end;
这样, 编译器终于不报错了, 可惜赋值完全无效...2次的Showmessage都是3
OK, 现在开始分析一下具体是怎么执行的
Unit1.pas.54: nList[3].Str := 'ABC'; 004B4C74 8D4DE8 lea ecx,[ebp-$18] 004B4C77 BA03000000 mov edx,$00000003 004B4C7C 8BC6 mov eax,esi 004B4C7E E83D0F0000 call Generics + $4B5BC0 004B4C83 8D45E8 lea eax,[ebp-$18] 004B4C86 BA204D4B00 mov edx,$004b4d20 004B4C8B E8B0000000 call Generics + $4B4D40
显然, 一开始先吧list里的内容复制出来一份临时数据, 然后给这个临时数据赋值, 然后...就没有然后了
只是改变的临时数据, list里的内容完全没变化啊
于是, 瞬间联想到, 如果一个类实例里的某一属性是结构体的话, 那么对其赋值和取值, 也是基于创建一个临时变量,修改其内容再全部替换的过程
这样就好解释多了, 看来是不能直接修改结构体的单独一项, 那咱们换个方法
TRC = record Str: string; Int: Integer; end; ... var nRC: TRC; nList: TList<TRC>; i: Integer; begin nList := TList<TRC>.Create; for i := 0 to 9 do begin with nRC do begin Str := IntToStr(i); Int := i; end; nList.Add(nRC); end; ShowMessage(nList[3].Str); nRC := nList[3]; nRC.Str := 'ABC'; nList[3] := nRC; ShowMessage(nList[3].Str); nList.Free; end;
这样果然没问题了
至于结构体为啥不能再类实例里直接修改其内部元素的问题, 这个有待继续研究...
--------------------------------------------------------------------------------------------------
作者:黑暗煎饼果子
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利.
--------------------------------------------------------------------------------------------------