如果不在Delphi中使用约束,如何判断泛型类型是否为nil?

如果不在Delphi中使用约束,如何判断泛型类型是否为nil?,delphi,Delphi,我想检查泛型类型是否在不使用约束的情况下“有效” 换句话说,我想编写以下代码: class function TMaybe<T>.FromValue(aValue: T): TMaybe<T>; begin if T <> nil then begin Result := TMaybe<T>.Some(aValue); end else begin Result := TMaybe<T>.None;

我想检查泛型类型是否在不使用约束的情况下“有效”

换句话说,我想编写以下代码:

class function TMaybe<T>.FromValue(aValue: T): TMaybe<T>;
begin
  if T <> nil then
  begin
    Result := TMaybe<T>.Some(aValue);
  end else
  begin
    Result := TMaybe<T>.None;
  end;
end;
显然,对于这样一个类,我希望任何类型都可以是tmaye

有没有办法检查无约束类型是否为“有效”,即不为null?(我不关心空字符串等)


我应该写一个
TypeIsEmpty(aValue:T):Boolean
来使用TypInfo来计算它吗?我想避免这种情况。

试试这样:

类型
PMethod=^TMethod;
类函数TMaybe.FromValue(aValue:T):TMaybe;
开始
{
如果T为,则*undocumented*IsManagedType()内在函数返回True
是接口、字符串或动态数组,但如果T
是包含这样一个字段的记录。因为记录不能与
nil,IsManagedType(T)在这里不有用。
可以使用*undocumented*GetTypeKind()内部函数
而是只处理可为零的类型。。。
}
//如果是IsManagedType(T),则。。。
案例类型(T)
tkString,tkClass,tkLString,tkWString,tkInterface,tkDynArray,tkString:
开始
如果PPointer(@aValue)^=nil,则
退出(t可能无);
结束;
TK方法:
开始
如果(PMethod(@aValue)^.Data=nil)或(PMethod(@aValue)^.Code=nil),则
退出(t可能无);
结束;
结束;
退出(TMaybe.Some(aValue));
结束;
GetTypeKind()
(和
IsManagedType()
)这样的内在函数在编译时进行求值,因此求值为
False
的代码分支在最终可执行文件中进行优化。然而,正如@DavidHeffernan在注释中提到的,编译器在实例化泛型之前会检查代码语法,因此,
PPointer
typecast可以解决这个问题

因此,如果您将
T
设置为可为零的类型,如字符串,编译器将能够将代码优化为:

类函数TMaybe.FromValue(aValue:String):TMaybe;
开始
如果指针(aValue)=nil,则
退出(t可能无);
退出(TMaybe.Some(aValue));
结束;
如果您将
T
设置为不可为零的类型,如整数,编译器将能够将代码优化为以下类型:

类函数TMaybe.FromValue(aValue:Integer):TMaybe;
开始
退出(TMaybe.Some(aValue));
结束;

您有什么特别担心为什么要避免使用TypInfo吗?编译器内部例程是否有帮助?请阅读@RudyVelthuis的这篇文章,保佑他的灵魂:。还有@LURD:哦,天哪。我不知道。他会被怀念的。@KenBourassa我通常会因为表现原因而避开RTTI。但当然,有时,就像这里一样,这是唯一的方法。
如果aValue=nil,则不使用E2015编译。我想您可以通过在case语句中进行一些指针转换来修复它。类似于
如果PPointer(@aValue)^=nil,则
。双指针方法需要另一个分支。错误的推理是编译器语法在实例化泛型之前检查代码。如果这些是模板,您的推理就可以了。而且,字符串类型位于错误的位置。在语言级别上,它们不可能是
nil
。当然,空字符串是这样实现的,但是如果s=nil,则不能写入
,因此它们属于另一个分支。但这并不是重点,尼克可以决定游戏规则。@DavidHeffernan字符串被实现为指针,因此
PPointer
typecast也适用于它们,不需要另一个代码分支单独处理它们。但是
t方法
有点不同。我更新了答案。代码编译并运行字符串。我没有说别的。这在逻辑上是错误的。因为字符串没有空值。太棒了——谢谢你,雷米。我希望有一个稍微干净一点的方法,但这是极好的。谢谢
E2571 Type parameter 'T' doesn't have class or interface constraint