【发布时间】:2020-09-23 15:01:48
【问题描述】:
我正在尝试在 Delphi 中创建一个可为空的数据类型:
type
TNullable<T> = record
public
Value: T;
IsNull: Boolean;
class operator Implicit(const AValue: T): TNullable<T>;
class operator Implicit(const AValue: TNullable<T>): T;
class operator Implicit(const AValue: Variant): TNullable<T>;
class operator Explicit(const AValue: T): TNullable<T>;
end;
到目前为止一切都很好,但是应该将什么分配为null 文字,以使可空数据类型保持其基本类型?例如:
var
v: TNullable<Integer>;
begin
//What type is this "null"? A Variant null?
//How TNullable<Integer> could remain of Integer after the assignment?
v := null;
//How to compare this "null"? Compare to what type?
if v = null then begin
end;
end;
让我们假设 null 是变体 null:
class operator TNullable<T>.Implicit(const AValue: Variant): TNullable<T>;
begin
if VarIsNull(AValue) or VarIsClear(AValue) then begin
Result.IsNull := True;
Result.Value := Default(T);
end
else begin
Result.IsNull := False;
Result.Value := AValue; //Version 1: Incompatible types: 'T' and 'Variant'!!!
Result.Value := T(AValue); //Version 2: Invalid typecast!!!
//Should I write a big "case" block here in order to handle each data type?!
end;
end;
你有什么想法吗?
【问题讨论】:
-
T,因此 Value 可以是任何类型,包括变量与赋值不兼容的东西,例如记录。我知道(好吧,假设)你只打算使用兼容类型,但编译器不知道
-
当然有很多方法可以创建
TNullable<T>。就个人而言,我认为我会在不涉及变体的情况下这样做。所以我的空符号不是null,而是自定义类型。 -
一个空记录就足够了,可以作为单独的类型,也可以作为
TNullable的嵌套类型。另一种方法是简单地将SetNull()方法添加到TNullable。 -
@Paul
null是 C# 中的实际关键字,类似于 C++11 中的nullptr。它们都是不同的,并且由编译器进行特殊处理。目前在 Delphi 中最接近的东西是nil,但如果T是引用类型,这可能会导致冲突。因此,在 Delphi 中,如果您想对TNullable值使用赋值语法,则为您的null值声明一个不同的类型(例如空记录)是下一个最佳选择。 -
存在严重的设计问题:1) 您应该在
private部分隐藏 TNullable记录内部。 2) 在 IsNull字段中保持空状态不是一个好主意。当您构造default(TNullable<T>)时,它的IsNull将初始化为false,这可能不是您想要的。你最好叫它HasValue.. similar to C#.
标签: delphi nullable delphi-xe5