问题
Why variables are declared as TStrings
and created as TStringList
?
eg: the var sl
is declared as TStrings
but created as TStringList
var
sl : TStrings;
begin
sl := TStringList.Create;
// add string values...
sl.Add( 'Delphi' );
sl.Add( '2.01' );
// get string value using its index
// sl.Strings( 0 ) will return
// 'Delphi'
MessageDlg(
sl.Strings[ 0 ],
mtInformation, [mbOk], 0 );
sl.Free;
end;
回答1:
To my mind that is rather pointless albeit completely harmless. You could perfectly well declare sl
to be TStringList
and I would always do it that way. For a reader of the code it makes the list of local variables easier to understand.
In this code sl
is always assigned a TStringList
instance and so there's nothing to be gained from declaring sl
to have the base class type of TStrings
. However, if you had code that assigned a variety of different types of TStrings
descendants to the variable, then it would make sense to declare it as TStrings
.
The situations when you might declare a variable to be of type TStrings
would typically be when the code was not explicitly creating the instance. For example a utility method that received a string list as a parameter would be more useful if it accepted a TStrings
since then any descendant could be passed to it. Here's a simple example:
procedure PrintToStdOut(Strings: TStrings);
var
Item: string;
begin
for Item in Strings do
Writeln(Item);
end;
Clearly this is of much greater utility when the parameter is declared to be TStrings
rather than TStringList
.
However, the code in the question is not of this nature and I believe that it would be ever so mildly improved if sl
was declared to be of type TStringList
.
回答2:
TStrings
is an abstract type that doesn't have all methods implemented.
TStringList
is a descendant of TStrings
and implements all functions. In your code, you could declare your variable also as TStringList
.
However e.g. on function definitions it makes sense to accept a TStrings
parameter instead of a TStringList
:
procedure doSomething(lst: TStrings);
This enables the function to work with all implementations of TStrings
, not only TStringList
.
回答3:
Because that way you could put another TStrings
descendant in the SL
variable (I'd probably call that Strings
, not SL
).
In your case, that is moot, since the logic around SL
contains the creation of a TStringList
and no external assignment or parameter parsing.
But if you ever split the logic away from the assignment, then you could benefit from using any TStrings
descendant.
For instance, a TMemoy.Lines
, TListBox.Items
, TComboBox.Items
, etc.
From the outside it looks like they are TStrings
, but internally they do not use a TStringList
but their own descendant.
A few examples of classes that descend from TStrings
:
source\DUnit\Contrib\DUnitWizard\Source\DelphiExperts\Common\XP_OTAEditorUtils.pas:
TXPEditorStrings = class(TStrings)
source\fmx\FMX.ListBox.pas:
TListBoxStrings = class(TStrings)
source\fmx\FMX.Memo.pas:
TMemoLines = class(TStrings)
source\rtl\common\System.Classes.pas:
TStringList = class(TStrings)
source\vcl\Vcl.ComCtrls.pas:
TTabStrings = class(TStrings)
TTreeStrings = class(TStrings)
TRichEditStrings = class(TStrings)
source\vcl\Vcl.ExtCtrls.pas:
TPageAccess = class(TStrings)
THeaderStrings = class(TStrings)
source\vcl\Vcl.Grids.pas:
TStringGridStrings = class(TStrings)
TStringSparseList = class(TStrings)
source\vcl\Vcl.Outline.pas:
TOutlineStrings = class(TStrings)
source\vcl\Vcl.StdCtrls.pas:
TCustomComboBoxStrings = class(TStrings)
TMemoStrings = class(TStrings)
TListBoxStrings = class(TStrings)
source\vcl\Vcl.TabNotBk.pas:
TTabPageAccess = class(TStrings)
回答4:
a TStringList is a concrete implementation of the abstract TStrings class
来源:https://stackoverflow.com/questions/9379607/why-variables-are-declared-as-tstrings-and-created-as-tstringlist