Попробуйте что-то вроде этого:
type
PMethod = ^TMethod;
class function TMaybe<T>.FromValue(aValue: T): TMaybe<T>;
begin
{
the *undocumented* IsManagedType() intrinsic function returns True if T
is an interface, string, or dynamic array, but it also returns True if T
is a record containing such a field. Since a record can't be compared to
nil, IsManagedType(T) is not useful here.
Using the *undocumented* GetTypeKind() intrinsic function can be used
instead to handle ONLY nil-able types...
}
// if IsManagedType(T) then...
case GetTypeKind(T) of
tkString, tkClass, tkLString, tkWString, tkInterface, tkDynArray, tkUString:
begin
if PPointer(@aValue)^ = nil then
Exit(TMaybe<T>.None);
end;
tkMethod:
begin
if (PMethod(@aValue)^.Data = nil) or (PMethod(@aValue)^.Code = nil) then
Exit(TMaybe<T>.None);
end;
end;
Exit(TMaybe<T>.Some(aValue));
end;
Intrinsi c Функции, такие как GetTypeKind()
(и IsManagedType()
), оцениваются во время компиляции и как такие ветви кода с оценкой False
оптимизируются из окончательного исполняемого файла. Тем не менее, как @DavidHeffernan упоминает в комментариях, компилятор проверяет синтаксис кода, прежде чем он создает экземпляр generi c, следовательно, PPointer
typecast, чтобы обойти это.
Итак, если вы установите T
в с нулевым типом, например String, компилятор сможет оптимизировать код до следующего:
class function TMaybe<String>.FromValue(aValue: String): TMaybe<String>;
begin
if Pointer(aValue) = nil then
Exit(TMaybe<String>.None);
Exit(TMaybe<String>.Some(aValue));
end;
И если вы установите T
для типа, не являющегося ноль, например, Integer компилятор сможет оптимизировать код до этого:
class function TMaybe<Integer>.FromValue(aValue: Integer): TMaybe<Integer>;
begin
Exit(TMaybe<Integer>.Some(aValue));
end;