Reputation: 3238
In Delphi Rio, I have created a class whose purpose is to read a record from a database. This record is purely read only, and after reading, I need to derive some additional properties. My problem has to do with a Stringlist I am wanting to use in my class definition. I have a private class member called fVENDORS_TO_COLORCODE. This is a comma separated string. I am wanting to make a property that is a TStringlist. I am using TStringList.CommaToText to load my value into the Tstringlist. I do this in the Create Constructor. The issue I am having is that while the StringList is valid in the constructor, it is nil outside of the constructor, and I don't know what I am doing wrong. Here is the relevant portions of code.
type
TProfileDef = class(TObject)
private
fNAME: String;
fVENDORS_TO_COLORCODE: String; // incoming comma separated string. Example string: Microsoft,IBM
fVENDORS_TO_COLORCODE_SL : TStringList;
..
public
constructor Create(ProfileName: String);
destructor Destroy; override;
published
property NAME: String read fNAME;
property VENDORS_TO_COLORCODE: String read fVENDORS_TO_COLORCODE;
property VENDORS_TO_COLORCODE_SL : TStringList read fVENDORS_TO_COLORCODE_SL;
..
end;
implementation
destructor TProfileDef.Destroy;
begin
inherited;
fVENDORS_TO_COLORCODE_SL.Free;
end;
constructor TProfileDef.Create(ProfileName: String);
var
fVENDORS_SL: TStringList;
fVENDORS_TO_COLORCODE_SL: TStringList;
TempVendorList : String;
begin
inherited Create;
fName := ProfileName;
.. [Find my record based on ProfileName, and load the DB columns into the private variables]..
// Load the Color Code String into a StringList;
fVENDORS_TO_COLORCODE_SL := TStringList.Create;
fVENDORS_TO_COLORCODE_SL.CommaToText := fVENDORS_TO_COLORCODE;
end;
Within the Constructor, the fVENDORS_TO_COLORCODE_SL stringlist is created, and data is added... The issue is when I try to use it...
var
TestClass: TProfileDef;
begin
TestClass := TProfileDef.Create('Sample Profile');
// TestClass.Name is valid
// TestClass.VENDORS_TO_COLORCODE_SL is nil, and trying to access gives AV
Somehow I am defining this wrong, but I can't determine what it is is, in order to correct it.
Upvotes: 0
Views: 384
Reputation: 344
// Load the Color Code String into a StringList;
fVENDORS_TO_COLORCODE_SL := TStringList.Create;
This line here in the constructor is the problem. You have two variables named fVENDORS_TO_COLORCODE_SL
. One is a private member of the class declared in the private
section of th class declaration, the other is a local variable declared in the var
section of the constructor.
Guess which one takes precedence. That's right, the local variable in the constructor. That line initialized the local variable named fVENDORS_TO_COLORCODE_SL
, the private class member with the same name is still nil
.
As a general rule I preface local variables in a method with an l and only preface class members with an f to avoid just this sort of problem.
Rename your local variables in the constructor like so:
constructor TProfileDef.Create(ProfileName: String);
var
lVENDORS_SL: TStringList;
lVENDORS_TO_COLORCODE_SL: TStringList;
lTempVendorList : String;
begin
Then update your code and rebuild. Things should start to become obvious pretty quickly.
Upvotes: 0
Reputation: 108919
Your class has a private field
fVENDORS_TO_COLORCODE_SL: TStringList;
Your constructor should create a TStringList
object and have this variable point to it. I assume that is your intention, at least. However, your constructor has a local variable with the same name, fVENDORS_TO_COLORCODE_SL
, so the line
fVENDORS_TO_COLORCODE_SL := TStringList.Create;
indeed creates a TStringList
object, but the pointer is saved to this local variable, and the class's field with the same name remains nil
.
Solution: Remove the declaration of the local variable in the constructor.
Upvotes: 5