10

今日のレイモンド・チェンのブログエントリは、私が抱えている問題のエレガントな解決策に気づきました。

すべての構造をとるのではなく、さまざまなシェル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): ...

そして、私は正しいものを渡していると信じなければなりません。そして私は開発者(例えば)が次の違いを知っていると信じています:

  • パス_
  • ファイル
  • フォルダ

「型付き」文字列を使用するように関数を変更したい:

 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;

私が欲しいのは「異なる」タイプの文字列です。つまりstring、長さのプレフィックスが付けられ、参照カウントされ、nullで終了する場合に限ります。

4

3 に答える 3

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割り当てる方法を指定できます。TFileNameImplicit
于 2013-01-24T18:24:23.117 に答える
8

文字列タイプごとに異なるレコードタイプを作成します。文字列タイプは互換性がありますが、個別のレコードタイプは割り当て互換性がありません。

type
  TFullPath = record value: string end;
  TFolderOnly = record value: string end;

Chenの記事では、新しいシェル機能を、異なるハンドルタイプを作成する従来のSTRICTマクロと比較しています。覚えているように、異なる構造体を宣言することは、STRICTマクロがどのように機能するかを正確に示しています。

于 2013-01-24T18:19:05.303 に答える
2

Delphiが基本的な型を処理する方法で、これは「ここからそこに到達できない」場合であると私はかなり思っています。

文字列型の宣言はすべて、型の互換性と割り当ての互換性に関するDelphiの規則を満たします。彼らが制限するのは、varパラメーターを使用した手続き型宣言です。関数宣言を参照パラメーターや値パラメーターではなくvarパラメーターに変更した場合、最終的な例でコンパイルエラーが発生します。

とはいえ、とにかくそれはすべて役に立たない。タイプがあっても、入力がファイル名のみであることを確認する方法はまだありませTFilenameOnlyん。とにかく、プロシージャの内容をテストする必要があります。

于 2013-01-24T18:19:16.907 に答える