如何创建一个字符串类型?

Ian*_*oyd 10 delphi types delphi-5

一个来自雷蒙德陈今天博客文章让我体会到优雅的解决方案我有一个问题.

各种shell函数,而不是所有的ITEM­ID­LIST结构,只能接受:

  • ITEM­ID_CHILD
  • ID­LIST_RELATIVE
  • ID­LIST_ABSOLUTE
  • ITEM­ID_CHILD_ARRAY

结构.结构都是相同的,但现在您可以在编译器级别强制执行概念类型.

回到Delphi

我有一套功能:

  • 有些人走一条路:(例如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): ...
Run Code Online (Sandbox Code Playgroud)

我必须相信我传递了正确的东西; 而且我相信开发人员(例如),知道以下两者之间的区别:

  • 一条
  • 一个文件名
  • 和一个文件夹

我想更改函数以使用"类型"字符串:

 function GetFilenames(Folder: TFolderOnly; ...): ...
 function IsValidBatchFilename(Path: TFullPath): ...
 function GetReportType(Filename: TFilenameOnly): ...
Run Code Online (Sandbox Code Playgroud)

哪里:

type
   TFullPath = type string;
   TFolderOnly = type string;
   TFilenameOnly = type string;
Run Code Online (Sandbox Code Playgroud)

除了没有实际打字发生:

var
   dropFolder: string;
begin
   dropFolder := GetDropFolderPath(LCT);

   GetFilenames(dropFolder); <-- no compile error

end;
Run Code Online (Sandbox Code Playgroud)

我想要的是一种"不同"类型的字符串; 即string,只要它是长度前缀,参考计数,空值终止.

And*_*and 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;
Run Code Online (Sandbox Code Playgroud)

同样的TPathTFolder.好处:

  • 期望的功能TPath将不接受TFileName(或其他组合).
  • 您仍然可以TPath为常规字符串分配一个.如果从字符串转换为a TPath,则会自动检查字符串以查看它是否包含有效路径.
  • (可选)您可以通过编写更多类运算符来指定如何将(或其他组合)TPath分配给TFileName(或其他组合)Implicit.

  • 虽然我认为在Delphi 5中不可能,但这是个好主意![1] (3认同)

Rob*_*edy 8

为每种字符串类型创建不同的记录类型.不同的记录类型不是赋值兼容的,即使字符串类型是.

type
  TFullPath = record value: string end;
  TFolderOnly = record value: string end;
Run Code Online (Sandbox Code Playgroud)

Chen的文章将新的shell特性与经典的STRICT宏进行了比较,后者产生了不同的句柄类型,我记得,声明不同的结构正是STRICT宏的工作原理.