0

所以我在德爾福2007年工作,我正在清理我的代碼。我已經注意到,在很多程序中,我聲明瞭許多相同類型的不同變量。如何將一組對象傳遞給創建函數?

例如我現在看到的一個過程我聲明瞭4個不同的字符串列表,我必須爲每個字符串輸入var1 := TStringList.Create

我有一個想法,使一個程序,接受一個開放的變量數組,我的4個變量列表,然後創建它們全部。呼叫會是這樣的

CreateStringLists([var1,var2,var3,var4]); 

但至於我的知識,你無法通過引用傳遞的開放數組,因此不能做什麼,我希望能。有沒有人有關於此的任何有趣的想法?

回答

4

你可以用Delphi來做任何事情(或幾乎任何事情)。我不建議將下面的代碼使用,只需知道,關鍵是可能的:

type 
    PStringList = ^TStringList; 

procedure CreateStringLists(const SL: array of PStringList); 
var 
    I: Integer; 

begin 
    for I:= 0 to High(SL) do begin 
    SL[I]^:= TStringList.Create; 
    end; 
end; 

procedure TForm1.Button2Click(Sender: TObject); 
var 
    SL1, SL2, SL3: TStringList; 

begin 
    CreateStringLists([@SL1, @SL2, @SL3]); 
    SL3.Add('123'); 
    Caption:= SL3[0]; 
    SL1.Free; 
    SL2.Free; 
    SL3.Free; 
end; 
+0

+1我懷疑自己可以這樣做,但它很安全,很偷偷摸摸 - 很好! – 2011-01-05 20:30:02

+0

+1你打敗了我!我現在有我自己的基於普通指針的實現,我只是將它升級到使用指向TStringList的指針時注意到你的答案。 :) – jachguate 2011-01-05 20:39:55

+0

我認爲,當然,您必須在CreateStringLists過程中使其異常感知,因此所有這些都成功創建,或者在以特殊方式退出例程之前釋放所有已創建的過程。 – jachguate 2011-01-05 20:41:59

1

您可以創建一系列帶有2,3,4等參數的重載版本。例如:

procedure CreateStringLists(var L1, L2: TStringList); overload; 
procedure CreateStringLists(var L1, L2, L3: TStringList); overload; 
procedure CreateStringLists(var L1, L2, L3, L4: TStringList); overload; 

procedure CreateStringLists(var L1, L2: TStringList); 
begin 
    L1 := nil; 
    L2 := nil; 
    Try 
    L1 := TStringList.Create; 
    L2 := TStringList.Create; 
    Except 
    FreeAndNil(L2); 
    FreeAndNil(L1); 
    raise; 
    End; 
end; 

// etc. 

如果我這樣做,我會寫一個腳本來生成代碼。另外,在我自己的代碼中,我會在該函數的開始處編寫InitialiseNil(L1, L2),在異常處理函數中編寫FreeAndNil(L2, L1)InitialiseNilFreeAndNil是由一個非常簡單的Python腳本生成的函數,該腳本作爲註釋包含在代碼庫中,以便它可以重新運行。像上面定義的CreareStringLists這樣的程序只有在你有一個匹配的例程才能一次性釋放它們時纔有用。這允許你寫:

CreateStringLists(L1, L2); 
Try 
    // do stuff with L1, L2 
Finally 
    FreeAndNil(L2, L1); 
End; 

最後,我不是說我一定會做到這一點,但是這意味着作爲一個天真的和直接的問題的答案。作爲@ T.E.D。狀態,這樣做的需要表明代碼庫中存在更深層次的問題。

+0

+1我會將這與Serg的解決方案結合起來:讓他的一個私人,並揭露你的代碼,因爲它是更乾淨。 – 2011-01-06 16:39:27

1

其實,4個構造函數有什麼問題?

+2

其實,這看起來像一個評論,而不是一個真正的答案。 – jachguate 2011-01-05 20:13:05

+0

在功能上什麼都沒有,從視覺上來說,它會使我所看到的代碼更短,對我來說更容易查看。 – Tim 2011-01-06 12:40:31

5

通常在重構中,你需要採取一個廣泛的代碼視圖。爲什麼要「清理」這樣的幾個操作,而最有可能你根本就不應該做這些操作?

在這種情況下,我覺得你有一個例程需要處理4個單獨的字符串列表。這似乎不太可能具有良好的凝聚力。也許相反,它應該是一個被稱爲四次的字符串列表處理例程。所以我真的很想看到整個例程,而不是評論如何使它更漂亮。

+0

+1看大圖! – 2011-01-05 20:13:19

+0

我正在開發一些簡單化的演示軟件,這與幻燈片(powerpoint esq)演示文稿特別相關。在每張幻燈片上,我都有3個不同的文本可以使用的區域:正文,標題,版權。然後是另一個處理從文本文件解析文本的字符串列表,這是幻燈片保存到磁盤的方式。它們都是爲了一個獨特的目的而創建的。我喜歡你的回答......我會考慮這個問題。 – Tim 2011-01-05 20:26:19

1

如果它在你的背景下才有意義,你可以聚集專門TObjectList內聲明。

type 
    TMyList<T:class,constructor> = class(TObjectList<T>) 
    public 
    procedure CreateItems(const ACount : integer); 
    end; 

procedure TMyList<T>.CreateItems(const ACount: integer); 
var 
    Index: Integer; 
begin 
    for Index := 0 to (ACount - 1) do Add(T.Create); 
end; 

// Test procedure 
procedure TestMe; 
var 
    MyStringsList : TMyList<TStringList>; 
begin 
    MyStringsList := TMyList<TStringList>.Create(True); 
    MyStringsList.CreateItems(10); 
    // ... 
    FreeAndNil(MyStringsList); 
end; 

所以你可以專門化你的清單。