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

时间:2013-01-24 18:08:52

标签: delphi types delphi-5

blog entry from Raymond Chen today让我意识到我遇到的问题的优雅解决方案。

各种 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): ...

我必须相信我传递了正确的东西;而且我相信开发人员(例如 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,只要它是长度前缀,引用计数,空终止。

3 个答案:

答案 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;

,同样适用于TPathTFolder。优点:

  • 期待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类型,您仍无法确保输入只是文件名,并且无论如何都必须测试过程中的内容。