我试图通过使用重载过程来创建一个带有无类型参数类型安全的旧API,比如说
// old, untyped API:
procedure DoItUntyped(var AEle; ASize: Integer);
begin
Writeln(ASize);
// Doing the real work (including modifications to AEle, therefore the "var")
end;
// New typed overloads:
procedure DoIt(var AEle: Word); overload;
begin
DoItUntyped(AEle, SizeOf(AEle));
end;
procedure DoIt(var AEle: Byte); overload;
begin
DoItUntyped(AEle, SizeOf(AEle));
end;
我现在可以这样使用:
procedure Test;
var
w: Word;
b: Byte;
e: TTextLineBreakStyle;
begin
DoIt(w);
DoIt(b);
DoIt(Byte(e));
end;
请注意,它甚至适用于枚举类型(如e
),只需很少的努力(一次演员)和非常类型安全(例如DoIt(Word(e));
无法编译)。
现在我想将这种技术扩展到数组。这对于内置类型很容易:
procedure DoIt(var AEle: array of Word); overload;
begin
DoItUntyped(AEle, SizeOf(AEle));
end;
procedure DoIt(var AEle: array of Byte); overload;
begin
DoItUntyped(AEle, SizeOf(AEle));
end;
procedure Test;
var
w3: array[0..3] of Word;
b3: array[0..3] of Byte;
w9: array[0..9] of Word;
b9: array[0..9] of Byte;
begin
DoIt(w3);
DoIt(b3);
DoIt(w9);
DoIt(b9);
end;
但是对于枚举数组来说它变得很难看。我可以介绍帮手类型:
procedure Test;
type
TB3 = array[0..3] of Byte;
TB9 = array[0..9] of Byte;
var
e3: array[0..3] of TTextLineBreakStyle;
e9: array[0..9] of TTextLineBreakStyle;
begin
DoIt(TB3(e3));
DoIt(TB9(e9));
end;
但我需要为每种类型和数组长度提供一种帮助器类型。另一种方法可能是为数组长度添加一个单独的参数,但这需要重复调用:
procedure DoItArray(var AFirstEle: Word; ALength: Integer); overload;
begin
DoItUntyped(AFirstEle, SizeOf(AFirstEle) * ALength);
end;
procedure DoItArray(var AFirstEle: Byte; ALength: Integer); overload;
begin
DoItUntyped(AFirstEle, SizeOf(AFirstEle) * ALength);
end;
procedure Test;
var
e3: array[0..3] of TTextLineBreakStyle;
e9: array[0..9] of TTextLineBreakStyle;
begin
DoItArray(Byte(e3[Low(e3)]), Length(e3));
DoItArray(Byte(e9[Low(e9)]), Length(e9));
end;
到目前为止,最佳解决方案似乎也为(可能很多)枚举类型添加了重载:
procedure DoIt(var AEle: TTextLineBreakStyle); overload;
procedure DoIt(var AEle: array of TTextLineBreakStyle); overload;
在我开始之前,我想知道是否有人有更少重复的想法。请注意,我们仍然必须使用D2007,所以没有泛型。
答案 0 :(得分:1)
从重载中删除var
说明符,除非您希望函数修改传入的变量,否则不需要它:
// old, untyped API:
procedure DoItUntyped(var AEle; ASize: Integer);
begin
Writeln(ASize);
// Doing the real work
end;
// New typed overloads:
procedure DoIt(AEle: Word); overload;
begin
DoItUntyped(AEle, SizeOf(AEle));
end;
procedure DoIt(AEle: Byte); overload;
begin
DoItUntyped(AEle, SizeOf(AEle));
end;
procedure Test;
var
w: Word;
b: Byte;
e: TTextLineBreakStyle;
begin
DoIt(w);
DoIt(b);
DoIt(Byte(e));
end;
然后可以像这样完成数组:
procedure DoIt(AEle: array of Word); overload;
begin
DoItUntyped(PWord(AEle)^, Length(AEle) * SizeOf(Word));
end;
procedure DoIt(AEle: array of Byte); overload;
begin
DoItUntyped(PByte(AEle)^, Length(AEle) * SizeOf(Byte));
end;
procedure DoIt(AEle: array of TTextLineBreakStyle); overload;
var
PTextLineBreakStyle = ^TTextLineBreakStyle;
begin
DoItUntyped(PTextLineBreakStyle(AEle)^, Length(AEle) * SizeOf(TTextLineBreakStyle));
end;
procedure Test;
var
w3: array[0..3] of Word;
b3: array[0..3] of Byte;
w9: array[0..9] of Word;
b9: array[0..9] of Byte;
e3: array[0..3] of TTextLineBreakStyle;
e9: array[0..9] of TTextLineBreakStyle;
begin
DoIt(w3);
DoIt(b3);
DoIt(w9);
DoIt(b9);
DoIt(e3);
DoIt(e9);
end;