blog entry from Raymond Chen today让我意识到我遇到的问题的优雅解决方案。
各种 shell 功能,而非所有采用ITEMIDLIST
结构的功能,只能接受:
ITEMID_CHILD
IDLIST_RELATIVE
IDLIST_ABSOLUTE
ITEMID_CHILD_ARRAY
结构。结构都相同,但现在您可以在编译器级别强制执行概念类型。
我有一套功能:
C:\Users\Ian\Desktop\AllisonAngel.jpg
)AllisonAngel.jpg
)C:\Users\Ian\Desktop
)现在他们都被宣布为string
,例如:
function GetFilenames(Folder: string; ...): ...
function IsValidBatchFilename(Path: string): ...
function GetReportType(Filename: string): ...
我必须相信我传递了正确的东西;而且我相信开发人员(例如 me ),知道:
之间的区别我想更改函数以使用“typed”字符串:
function GetFilenames(Folder: TFolderOnly; ...): ...
function IsValidBatchFilename(Path: TFullPath): ...
function GetReportType(Filename: TFilenameOnly): ...
其中:
type
TFullPath = type string;
TFolderOnly = type string;
TFilenameOnly = type string;
除了没有发生实际打字:
var
dropFolder: string;
begin
dropFolder := GetDropFolderPath(LCT);
GetFilenames(dropFolder); <-- no compile error
end;
我想要的是“distinct”类型的字符串;这是string
,只要它是长度前缀,引用计数,空终止。
答案 0 :(得分:9)
您可以使用高级记录来完成此任务。例如,你可以做
type
TFileName = record
FFileName: string;
public
class function IsValidFileName(const S: string): boolean; static;
class operator Implicit(const S: string): TFileName;
class operator Implicit(const S: TFileName): string;
end;
implementation
class function TFileName.IsValidFileName(const S: string): boolean;
begin
result := true {TODO};
end;
class operator TFileName.Implicit(const S: string): TFileName;
begin
if IsValidFileName(S) then
result.FFileName := S
else
raise Exception.CreateFmt('Invalid file name: "%s"', [S]);
end;
class operator TFileName.Implicit(const S: TFileName): string;
begin
result := S.FFileName;
end;
,同样适用于TPath
和TFolder
。优点:
TPath
的功能不接受TFileName
(或其他组合)。TPath
。如果从字符串转换为TPath
,您将自动检查字符串以查看它是否包含有效路径。TPath
类操作符来指定TFileName
如何分配给Implicit
(或其他组合)。答案 1 :(得分:8)
为每种字符串类型创建不同的记录类型。不同的记录类型不是赋值兼容的,即使字符串类型是。
type
TFullPath = record value: string end;
TFolderOnly = record value: string end;
Chen的文章将新的shell特性与经典的STRICT宏进行了比较,后者产生了不同的句柄类型,我记得,声明不同的结构正是STRICT宏的工作原理。
答案 2 :(得分:2)
通过Delphi处理基本类型的方式,我很漂亮这是一个&#34;你无法从这里到达那里。&#34;
您的字符串类型声明都将满足Delphi的类型兼容性和赋值兼容性规则。他们将限制的是具有var
参数的程序声明。如果您将函数声明更改为var参数而不是参考或值参数,则最终示例中会出现编译错误。
所有这一切,无论如何都没用。即使使用TFilenameOnly
类型,您仍无法确保输入只是文件名,并且无论如何都必须测试过程中的内容。