我有一个HashTable,我需要一些方法来返回not_found
结果。
type
TCell<T> = record
.....
property key: cardinal read FKey write FKey;
property data: T read FData write FData;
end;
THashTable<T> = class(TEnumerable<T>)
private
FCells: array of TCell<T>;
FEmpty: T;
...
constructor Create(InitialSize: cardinal); overload;
function Lookup(key: cardinal): T;
...
end;
constructor THashTable<T>.Create(InitialSize: cardinal);
begin
inherited Create;
// Initialize regular cells
FArraySize:= InitialSize;
Assert((FArraySize and (FArraySize - 1)) = 0); // Must be a power of 2
SetLength(FCells, FArraySize);
FillChar(FEmpty, SizeOf(FEmpty), #0); //Superfluous I know, just there to
//demonstrate the point.
end;
鉴于上述结构,我如何返回not found
结果?
如果我有指针,我会返回nil
指向T
的指针
但是不允许指向泛型类型的指针。
所以我想出了以下解决方案:
function THashTable<T>.Lookup(key: cardinal): T;
var
Cell: NativeUInt;
begin
if (key <> 0) then begin
// Check regular cells
Cell:= First_Cell(IntegerHash(key));
while (true) do begin
if (FCells[Cell].key = key) then Exit(FCells[Cell].data);
if not (FCells[Cell].key = 0) then Exit(FEmpty); <<-- is this correct?
Cell:= Circular_Next(Cell);
end;
end else begin
Result:= FEmpty; <<--- Can I return an empty generic like this?
end;
end;
我可以将零初始化通用返回到no result
吗?
或者我会遇到结构类型(类/记录/变体/字符串等)的问题。
请注意,我确实理解T
是整数时的歧义。零很可能是一个有效的值,因此它与not_found无法区分
我并不担心这些结果。
答案 0 :(得分:12)
您正在寻找的是default(T)
,它将为任何类型T返回零值。
答案 1 :(得分:3)
我建议更改函数以使用输出var
参数作为数据,然后您可以Boolean
使用Result
,例如:
function THashTable<T>.Lookup(key: cardinal; var Value: T): Boolean;
var
Cell: NativeUInt;
begin
Result := False;
if (key <> 0) then begin
// Check regular cells
Cell := First_Cell(IntegerHash(key));
while Cell <> -1 do begin
if (FCells[Cell].key = key) then begin
Value := FCells[Cell].data;
Exit(True);
end;
if (FCells[Cell].key <> 0) then Break;
Cell := Circular_Next(Cell);
end;
end;
end;
答案 2 :(得分:3)
@ S.MAHDI建议您可以编写此代码:
Result := T(nil);
我最初的反应是,这不会编译,因为演员表明显无效。例如,此代码无法编译:
var
P: Pointer;
....
Result := T(P);
对于该代码,编译器报告: E2089无效的类型转换。
但是T(nil)
的赋值确实编译了。当您查看生成的代码时,对于我调查的所有案例,代码与为Default(T)
生成的代码相同。
所以,我的结论是,这个显然没有文档的语法T(nil)
由编译器在泛型上下文中特别处理,并且是Default(T)
的别名。
我很想知道是否有人可以指出此功能的任何官方文档。
答案 3 :(得分:0)
我决定返回指向泛型类型的指针。
type
//P<T> = ^T;
P<T> = record {holding a pointer to T with some operator overloading}
....
FCells: array of T <<-- holds T directly now.
function THashTable<K,T>.Lookup(const key: K): P<T>;
begin
....
if found then Result:= @FCells[CorrectIndex]
else Result:= nil;
end;