2009-12-11 3 views
2

일반 컨테이너 (TList)로 레코드에 대해 약간 미쳤습니다 (Queen 's 노래 불러).델파이의 레코드 및 일반 컨테이너

TItemRec = record 
    private 
    FSender : TAction; 
    FOwnerPack : HModule; 
    FDockPanel : TdxDockPanel; 
    procedure SetDockPanel(const Value: TdxDockPanel); 
    procedure SetOwnerPack(const Value: HModule); 
    procedure SetSender(const Value: TAction); 
    public 
    property Sender: TAction read FSender write SetSender; 
    property OwnerPack: HModule read FOwnerPack write SetOwnerPack; 
    property DockPanel: TdxDockPanel read FDockPanel write SetDockPanel; 
    end; 

    TPackRec = record 
    private 
    FHandle : HModule; 
    var FCounter : Int16; 
    procedure SetCounter(const Value: Int16); 
    procedure SetHandle(const Value: HModule); 
    public 
    property Handle: HModule read FHandle write SetHandle; 
    property Counter: Int16 read FCounter write SetCounter; 
    procedure ChangeCounter(IncValue: Boolean = True); 
    end; 

    TRecList = class(TList<TItemRec>) 
    public 
    procedure CloseDockPanels; 
    end; 

    TPackList = class(TList<TPackRec>) 
    strict private 
    procedure DoChanges(const APack: HModule; const AAdd: Boolean = True); 
    public 
    procedure CheckForUnusedItems; 
    procedure AppendRef(const APack: HModule); 
    procedure DeleteRef(const APack: HModule); 
    procedure ClosePackages; 
    end; 

    TfrmMain = class(TForm) 
    private 
    FRecList : TRecList; 
    FPackList : TPackList; 
    public 
    end; 

........................ 

procedure TPackList.CheckForUnusedItems; 
var 
    i : Int16; 
    Flag : Boolean; 
begin 
    repeat 
    Flag:= False; 
    if Self.Count > 0 then begin 
     for i:= Self.Count - 1 downto 0 do begin 
     Flag:= Self.Items[i].FCounter > 0; 
     if not Flag then begin 
      Self.Delete(i); 
      Flag:= True; 
      Break; 
     end; 
     Flag:= False; 
     end; 
    end; 
    until not Flag; 
end; 

procedure TPackRec.ChangeCounter(IncValue: Boolean); 
var 
    Value : Int16; 
begin 
    Value:= Counter; 
    if IncValue then 
    Value:= Value + 1 
    else 
    Value:= Value - 1; 
    Counter:= Value; 
end; 

변화하는 값을 가진 유일한 항목입니다 카운터 재산에 대한 값을 변경하려고 할 때 나는 심각한 문제가있다 : 첫째,이 코드를 참조하십시오. ChangeCounter 메서드는 Counter의 값을 변경해야하며 분명히 완료되지만 CheckForUnusedItems 메서드의 경우 아무 것도 변경하지 않고 거의 모든 것을 시도했지만 TPackList 및 TRecList는 각각 상수로 보입니다.

항목이 성공적으로 추가 FRecList의

Pic01

항목

Pic02

ChangeCounter 방법은 카운터의

Pic03

을 값을 변경

삭제 : 나는 당신에게 사진을 보여 16,

CheckForUnusedItems 방법은

Pic04

카운터 속성이 일정한

무슨 일이 일어나고 무엇

Pic05

같은 값을 유지 어떤 변화를 볼 doesnot? 이것에 대한 설명이 있습니까? 어떻게 해결할 수 있습니까? 미리 감사드립니다.

답변

10

기본 인덱서 속성 TList복사본을 컨테이너 내부에 반환합니다. 그 사본에 ChangeCounter으로 전화하면 해당 사본의 필드가 변경됩니다. 컨테이너 안의 원래 항목은 변경되지 않았습니다. 작동 시키려면 로컬에 저장하고 해당 지역에 변형 메소드를 호출 한 다음 컨테이너에 로컬을 다시 저장하고 이전 값을 겹쳐 써야합니다.

"참조로 반환"할 방법이 없기 때문에 배열 이외의 다른 컨테이너에도 해당되므로 반환 값에 대한 추가 변형 작업이 컨테이너 자체에 반영됩니다.

+2

예! 이 객체가 잘 작동하는 이유는 객체가 참조 유형이기 때문에 복사 된 객체가 객체에 대한 포인터이기 때문입니다. 이것은 레코드의 경우가 아닙니다. –

0

좋아, 먼저 FCounter 전에 var가 필요하지 않지만 아무런 해를 끼치 지 않습니다. ChangeCounter 사용하지 왜 값 FCounter 들어있는 기록의 방법이기 때문에

다음 :

procedure TPackRec.ChangeCounter(IncValue: Boolean); 
begin 
    if IncValue then 
    Inc(FCounter) 
    else 
    Dec(FCounter); 
end; 

당신은 오버플로/언더 당신이 좋아하는 경우에 검사를 추가 할 수 있습니다.

레코드의 속성에 문제가 있습니다. 특히 레코드가 함수에 의해 반환되는 경우. 레코드를 로컬 변수에 할당하면이 문제가 해결됩니다.