不幸的是,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?
答案 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.Assign
是intrinsic函数。它的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
。相反,您应该使用AssignFile
。 documentation对你来说不是更好!
答案 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中需要它?