A blog entry from Raymond Chen today made me realize the elegant solution to a problem i'm having.
Various shell functions, rather than all taking ITEMIDLIST
structure, can be made to only accept:
ITEMID_CHILD
IDLIST_RELATIVE
IDLIST_ABSOLUTE
ITEMID_CHILD_ARRAY
structures. The structures are all identical, but now you can enforce conceptual types at the compiler level.
Back to Delphi
i have a set of functions:
- some only take a path: (e.g.
C:\Users\Ian\Desktop\AllisonAngel.jpg
) - some only take a filename: (e.g.
AllisonAngel.jpg
) - some only take a folder: (e.g.
C:\Users\Ian\Desktop
)
And right now they're all declared as string
, e.g.:
function GetFilenames(Folder: string; ...): ...
function IsValidBatchFilename(Path: string): ...
function GetReportType(Filename: string): ...
and i have to trust that i'm passing the right stuff; and i'm trusting that developers (e.g. me), know the difference between:
- a path
- a filename
- and a folder
i want to change the functions to use "typed" strings:
function GetFilenames(Folder: TFolderOnly; ...): ...
function IsValidBatchFilename(Path: TFullPath): ...
function GetReportType(Filename: TFilenameOnly): ...
Where:
type
TFullPath = type string;
TFolderOnly = type string;
TFilenameOnly = type string;
Except that there's no actual typing happening:
var
dropFolder: string;
begin
dropFolder := GetDropFolderPath(LCT);
GetFilenames(dropFolder); <-- no compile error
end;
What i want is a "distinct" type of string; that is string
insofar that it is length prefixed, reference counted, null terminated.