我想实现我自己的MySetLength()函数,该函数可能完全作为原始SetLength()(来自delphi 6)的数组,除了我想将 float 参数作为维度传递(然后,在调用原始Setlength()之前,最终将其绕入我的func中)。例如:
<label class="item item-input item-stacked-label" style="text-align:center">
<a class="button button-outline button-positive" href="#/app/nutrition" style="width:300px;">
SUBMIT
</a>
</label>
而不是原始:
procedure MySetLength(var A: Array type; Len1: **double**; Len2...);
其中A可以有任意数量的维度,可以是任何类型(字符串或浮点数)
答案 0 :(得分:2)
要实现它并使其完全像SetLength
那样工作,因为SetLength
是一个具有编译器和运行时支持的内在函数。这是函数如何能够接受任意数组和字符串类型,并接受任意数量的维度参数。只有编译器供应商才能发挥这样的作用。
你真的没有希望产生符合问题规范的任何远程有用的东西。最好的方法是直接调用SetLength
并将Round
函数应用于需要舍入的任何参数。
答案 1 :(得分:2)
出现了重载和泛型:
type
TMyHelper = class
public
class procedure SetLength(var A: String; Len: Double); overload; static;
class procedure SetLength<T>(var A: TArray<T>; Len: Double); overload; static;
class procedure SetLength<T>(var A: TArray<TArray<T>>; Len1, Len2: Double); overload; static;
// as so on...
end;
class procedure TMyHelper.SetLength(var A: String; Len: Double);
var
iLen: Integer;
begin
iLen := ...; // round Len as needed...
System.SetLength(A, iLen);
end;
class procedure TMyHelper.SetLength<T>(var A: TArray<T>; Len: Double);
var
iLen: Integer;
begin
iLen := ...; // round Len as needed...
System.SetLength(A, iLen);
end;
class procedure TMyHelper.SetLength<T>(var A: TArray<TArray<T>>; Len1, Len2: Double);
var
iLen1, iLen2: Integer;
begin
iLen1 := ...; // round Len1 as needed...
iLen2 := ...; // round Len2 as needed...
System.SetLength(A, iLen1, iLen2);
end;
// and so on...
var
s: string;
a1: TArray<Integer>;
a2: TArray<TArray<String>>;
begin
TMyHelper.SetLength(s, 10);
TMyHelper.SetLength<Integer>(a1, 10);
TMyHelper.SetLength<String>(a2, 5, 10);
end;
如果您使用的是不支持泛型的Delphi版本,则不能一般性地重载数组元素类型,但如果您使用的元素类型有限,您仍然可以重载数组,例如:
type
TInteger1DimArray = array of Integer;
TInteger2DimArray = array of TInteger1DimArray;
TString1DimArray = array of String;
TString2DimArray = array of TString1DimArray;
// and so on...
TMyHelper = class
public
class procedure SetLength(var A: String; Len: Double); overload; static;
class procedure SetLength(var A: TInteger1DimArray; Len: Double); overload; static;
class procedure SetLength(var A: TInteger2DimArray; Len1, Len2: Double); overload; static;
class procedure SetLength(var A: TString1DimArray; Len: Double); overload; static;
class procedure SetLength(var A: TString2DimArray; Len1, Len2: Double); overload; static;
// as so on...
end;
class procedure TMyHelper.SetLength(var A: String; Len: Double);
var
iLen: Integer;
begin
iLen := ...; // round Len as needed...
System.SetLength(A, iLen);
end;
class procedure TMyHelper.SetLength(var A: TInteger1DimArray; Len: Double);
var
iLen: Integer;
begin
iLen := ...; // round Len as needed...
System.SetLength(A, iLen);
end;
class procedure TMyHelper.SetLength(var A: TInteger2DimArray; Len1, Len2: Double);
var
iLen1, iLen2: Integer;
begin
iLen1 := ...; // round Len1 as needed...
iLen2 := ...; // round Len2 as needed...
System.SetLength(A, iLen1, iLen2);
end;
class procedure TMyHelper.SetLength(var A: TString1DimArray; Len: Double);
var
iLen: Integer;
begin
iLen := ...; // round Len as needed...
System.SetLength(A, iLen);
end;
class procedure TMyHelper.SetLength(var A: TString2DimArray; Len1, Len2: Double);
var
iLen1, iLen2: Integer;
begin
iLen1 := ...; // round Len1 as needed...
iLen2 := ...; // round Len2 as needed...
System.SetLength(A, iLen1, iLen2);
end;
// and so on...
var
s: string;
a1: TInteger1DimArray;
a2: TString2DimArray;
begin
TMyHelper.SetLength(s, 10);
TMyHelper.SetLength(a1, 10);
TMyHelper.SetLength(a2, 5, 10);
end;
正如您所看到的,为单个SetLength()
实现String
很容易,但对数组实现SetLength()
会变得非常复杂,具体取决于您使用的数组类型。此解决方案尽可能接近用户代码而无需借助RTTI,因此您可以直接调用RTL的DynArraySetLength()
函数。
答案 2 :(得分:2)
为什么试图解决重载或替换内在问题的问题复杂化?
为什么不实施您在替换 SetLength 中使用的舍入策略,并在适当的时候将其合并到您对内在函数的调用中?
SetLength(arr, ArrayDim(dbl));
当然,您保留了 SetLength 的所有功能,包括能够在必要时将双值的维度边界规则应用于多个维度:
SetLength(multiDimArr, ArrayDim(dblDim1), ArrayDim(dblDim2));
其中 ArrayDim (或者你认为合适的名称)是一个实现舍入策略并返回指定输入的相应数组维度(整数)的函数(<强>双强>)。
为什么要这样做而不是简单地使用 Round()?
答案是Delphi中的 Round()使用一种称为 Bankers Rounding 的特定舍入策略。这意味着 n.5 可以向上或向下,具体取决于 n 的值。
即使此舍入策略适合您当前的需求,您也应该实现一个函数,以明确应用适用于数组维度的特定舍入策略,并在 SetLength()调用中使用该策略。
这不仅确保您在每种情况下都应用正确的舍入策略,还意味着如果您需要或决定更改阵列维度的舍入策略,则只需更改功能 ,而不是使用该函数调用 SetLength() 。