System.Assign的确切签名是什么(用于程序表达式)?

时间:2013-04-15 14:06:55

标签: delphi

不幸的是,RTL源中没有准确的Assign签名,而我的猜测是,

const
  Assign: procedure (var F; const FileName: string) = System.Assign;
  { or }
  Assign: function (var F; const FileName: string): Integer = System.Assign;
  { also I tried "internal" one from _AssignFile }

没有产生任何正面结果,并且编译器拒绝将此类表达式视为程序性并且抱怨 right-value E2029 '(' expected but ';' found))。

那么,我应该使用哪种类型来完全匹配Delphi RTL?

3 个答案:

答案 0 :(得分:4)

Assign是Delphi的语言残余,它的起源是原始的Turbo Pascal语法。早在函数重载添加到语言语法之前很久,早在RTL的文本文件和“文件类型”内部数据结构被记录之前,就有Assign

Assign是一个足够简单的程序,但是当你看到它必须做什么时,你会发现如果没有某种编译器魔法,它几乎是不可能实现的。 File of TFoo创建的文件类型与File of Integer不同且不兼容。然而,两者都可以作为第一个参数传递给Assign

今天,您可以使用文件参数的泛型类型参数来实现Assign。泛型类型将符合传入的变量的类型。这很好,但是我们需要一种方法将类型化的文件变量与字符串文件名相关联,然后将25个字母文件添加到混合中。

Assign是编译器内部函数。这意味着它存在于Delphi / Pascal语法空间之外。 Assign本质上是一个类型一致的过程,它不能用强类型的Delphi / Pascal语言表示(没有现代和复杂的语言扩展,如泛型类型)。它不是无类型的,并且它不是动态类型的,因为实际参数类型在编译时完全确定。

您无法获取Assign功能的地址。即使你可以,因为它是无定形的,你将无法定义准确表示其所有可能的呼叫签名的过程类型。

编译器魔术函数存在于语言之外,用于处理当时可用语法无法轻易表示的任务。 Assign就是一个例子。 Writeln()是另一个。

答案 1 :(得分:2)

System.Assignintrinsic函数。它的official documentation完全没有希望。它说:

function Assign(var F: File; FileName: String; [CodePage: Word]): Integer; overload;
function Assign(var F: File; FileName: String; [CodePage: Word]): Integer; overload;
function Assign(var F: File; FileName: String; [CodePage: Word]): Integer; overload;

我只能猜测为什么文档生成器无法处理此功能。但三个完全相同的超载显然是假的。它不是一个功能,而是一个程序。

不管。因为它是内在的,所以不能将它分配给函数指针。解决方案是将其包装在您自己的功能中。

procedure MyAssign(var F: File; const FileName: string);
begin
  Result := System.Assign(F, FileName);
end;

然后,您可以将该函数分配给过程类型的变量或常量。

const
  AssignProc: procedure(var F: File; const FileName: string) = MyAssign;

Assign的另一个变体采用第三个参数来指定代码页,作为Word传递。如果Assign的第一个参数是TextFile,则只能调用该函数。

因此,内在函数本身就是一种法律。

请注意,文档确实说明不再使用Assign。相反,您应该使用AssignFiledocumentation对你来说不是更好!

答案 2 :(得分:0)

如果要打开System.pas文件并阅读它,在XE2中你有这些内部程序:

function _AssignFile(var t: TFileRec; const s: PChar): Integer;
function _AssignText(var t: TTextRec; const s: PChar; const CP: word): Integer;

并且我认为你没有任何全局稳定的程序,没有名称下划线 - 列出的是Delphi编译器内部,比如隐形程序,当你声明字符串或dynarray变量时隐蔽地调用它们。

http://en.wikipedia.org/wiki/Intrinsic_function

像许多像_Write0LString那样正在实现通常的WriteLn调用的程序。

所以你必须创建一个包装函数来调用AssignFile并将你的包装器引用到你的变量中;

但是你没有在你的Delphi版本中添加标签,并且不同的版本可能对内在函数有不同的声明。所以请查看特定Delphi的来源。

另外,你为什么需要它?我记得我在TurboPascal 5.5做了这样的事情来制作基于字符串的文件 - make WriteLn就像C sprintf一样。但是,当你可以使用TStream时,为什么在现代Delphi中需要它?