关于 Record & TList 的一点吐槽

需求是把record 保存在TList中,并可以随时改变TList中Items的各项值。

 

 代码很简单:

   MyRec = record

        MyStr: string;

        constructor Create(AMyStr: string);

end;

 

TForm4 = class(TForm)

  Button1: TButton;

  procedure Button1Click(Sender: TObject);

        public

  MyList: TList<MyRec>;

end;

 

constructor MyRec.Create(AMyStr: string);

begin

    MyStr := AMyStr;

end;

 

 

procedure TForm4.Button1Click(Sender: TObject);

begin

    MyList := TList<MyRec>.Create;

    MyList.Add(MyRec.Create('str'));

    MyList.Items[0].MyStr := 'www'; //[Error] Unit4.pas(46): E2064 Left side cannot be assigned to

    ShowMessage(MyList.Items[0].MyStr);

end;

 

 

无法赋值?想了一下,大概是因为左侧取出的是变量值本身,而不是变量,所以无法赋值。那么我取值地址再赋值总可以吧?于是改动如下:

 

procedure TForm4.Button1Click(Sender: TObject);

var

    ps: ^string;

begin

    MyList := TList<MyRec>.Create;

    MyList.Add(MyRec.Create('str'));

    ps := @MyList.Items[0].MyStr; //[DCC Error] Unit4.pas(45): E2036 Variable required

    ps^ := 'www';

    ShowMessage(MyList.Items[0].MyStr);

end;

 

 

必须为变量?又想了一下,大概是因为左侧取出的是变量值本身,而不是变量,所以无法取地址。那没办法,只能改一下TList,了,于是改动如下

Tpye

PMyRec = ^MyRec;

 

procedure TForm4.Button1Click(Sender: TObject);

begin

    MyList := TList<PMyRec>.Create;

    MyList.Add(MyRec.Create('str')); //[DCC Error] Unit4.pas(42): E2010 Incompatible types: 'PMyRec' and 'MyRec'

    MyList.Items[0].MyStr := 'www';

    ShowMessage(MyList.Items[0].MyStr);

end;

 

 

要是Create能返回指针就好了。不多说,继续改:

procedure TForm4.Button1Click(Sender: TObject);

begin

    MyList := TList<PMyRec>.Create;

    MyList.Add(@MyRec.Create('str')); //[DCC Error] Unit4.pas(42): E2036 Variable required

    MyList.Items[0].MyStr := 'www';

    ShowMessage(MyList.Items[0].MyStr);

end;

 

 

……。继续改:

procedure TForm4.Button1Click(Sender: TObject);

var

    r: MyRec;

begin

    MyList := TList<PMyRec>.Create;

    r := MyRec.Create('str');

    MyList.Add(@r);

    MyList.Items[0].MyStr := 'www';

    ShowMessage(MyList.Items[0].MyStr);

end;

 

 

看起来似乎是可以了,但是:

procedure TForm4.Button2Click(Sender: TObject);

begin

    ShowMessage(MyList.Items[0].MyStr); // Access Violation!

end;

 

 

想了一下,大概是r的内存被释放了。于是改动如下:

procedure TForm4.Button1Click(Sender: TObject);

var

    p: PMyRec;

begin

    MyList := TList<PMyRec>.Create;

    New(p);

    p.Create('str');

    MyList.Add(p);

    MyList.Items[0].MyStr := 'www';

    ShowMessage(MyList.Items[0].MyStr);

end;

 

 

OK了,不过真是麻烦,不用的时候还要dispose。感觉没有C++灵活。

posted on 2014-03-31 11:57  茅场晶彦  阅读(648)  评论(1编辑  收藏  举报

导航