<div dir="ltr"><span style="font-family:arial,helvetica,sans-serif">I've implemented a new version. For this version i created a mock class to use with FHasValue (the previous implementation uses a hack to the interface internal layout).</span><span style="font-family:monospace,monospace"><br><br><br>unit NullableTypes;<br><br>{$mode delphi}{$H+}<br><br>interface<br><br>type<br><br>  { TMockInterfacedObject }<br><br>  TMockInterfacedObject = class(TObject, IUnknown)<br>  strict private<br>    class var FInstance: TMockInterfacedObject;<br>  public<br>    class constructor Create;<br>    class destructor Destroy;<br>    class property Instance: TMockInterfacedObject read FInstance;<br>    function QueryInterface({$IFDEF FPC_HAS_CONSTREF}constref{$ELSE}const{$ENDIF} iid : tguid;out obj) : longint;{$IFNDEF WINDOWS}cdecl{$ELSE}stdcall{$ENDIF};<br>    function _AddRef: longint; {$IFNDEF WINDOWS}cdecl{$ELSE}stdcall{$ENDIF};<br>    function _Release: longint; {$IFNDEF WINDOWS}cdecl{$ELSE}stdcall{$ENDIF};<br>  end;<br><br>  { TNullable }<br><br>  TNullable<T> = record<br>  strict private<br>    FValue: T;<br>    FHasValue: IInterface;<br>    function GetValue: T;<br>    function GetHasValue: Boolean;<br>    procedure SetValue(const AValue: T);<br>    procedure SetFlatInterface(var Intf: IInterface);<br>  public<br>    constructor Create(const AValue: T);<br>    procedure Clear;<br>    function GetValueOrDefault: T; overload;<br>    function GetValueOrDefault(Default: T): T; overload;<br>    property HasValue: Boolean read GetHasValue;<br>    property Value: T read GetValue;<br><br>    class operator Implicit(const AValue: Pointer): TNullable<T>;<br>    class operator Implicit(AValue: TNullable<T>): T;<br>    class operator Implicit(const AValue: T): TNullable<T>;<br>    class operator Explicit(AValue: TNullable<T>): T;<br>  end;<br><br><br>  TInteger = TNullable<Integer>;<br><br>implementation<br><br>uses<br>  SysUtils;<br><br>{ TNullable }<br><br>procedure TNullable<T>.SetFlatInterface(var Intf: IInterface);<br>begin<br>  Intf := TMockInterfacedObject.Instance;<br>end;<br><br>class operator TNullable<T>.Explicit(AValue: TNullable<T>): T;<br>begin<br>  Result := AValue.Value;<br>end;<br><br>function TNullable<T>.GetHasValue: Boolean;<br>begin<br>  Result := FHasValue <> nil;<br>end;<br><br>function TNullable<T>.GetValue: T;<br>begin<br>  if not HasValue then<br>    raise Exception.Create('Invalid operation, Nullable type has no value');<br>  Result := FValue;<br>end;<br><br>function TNullable<T>.GetValueOrDefault: T;<br>begin<br>  if HasValue then<br>    Result := FValue<br>  else<br>   Result := Default(T);<br>end;<br><br>function TNullable<T>.GetValueOrDefault(Default: T): T;<br>begin<br>  if not HasValue then<br>    Result := Default<br>  else<br>    Result := FValue;<br>end;<br><br>class operator TNullable<T>.Implicit(const AValue: Pointer): TNullable<T>;<br>begin<br>  if AValue = nil then<br>    Result.Clear<br>  else<br>    raise Exception.Create('Invalid operation, incompatible values.');<br>end;<br><br>class operator TNullable<T>.Implicit(AValue: TNullable<T>): T;<br>begin<br>  Result := AValue.Value;<br>end;<br><br>class operator TNullable<T>.Implicit(const AValue: T): TNullable<T>;<br>begin<br>  Result := TNullable<T>.Create(AValue);<br>end;<br><br>procedure TNullable<T>.SetValue(const AValue: T);<br>begin<br>  FValue := AValue;<br>  SetFlatInterface(FHasValue);<br>end;<br><br>constructor TNullable<T>.Create(const AValue: T);<br>begin<br>  FValue := AValue;<br>  SetFlatInterface(FHasValue);<br>end;<br><br>procedure TNullable<T>.Clear;<br>begin<br>  FHasValue := nil;<br>end;<br><br>{ TMockInterfacedObject }<br><br>class constructor TMockInterfacedObject.Create;<br>begin<br>  FInstance := TMockInterfacedObject.Create;<br>end;<br><br>class destructor TMockInterfacedObject.Destroy;<br>begin<br>  FInstance.Free;<br>end;<br><br>function TMockInterfacedObject.QueryInterface({$IFDEF FPC_HAS_CONSTREF}constref<br>  {$ELSE}const{$ENDIF} iid : tguid;out obj): longint;<br>begin<br>  Result := E_NOINTERFACE;<br>end;<br><br>function TMockInterfacedObject._AddRef: longint;<br>begin<br>  Result := -1;<br>end;<br><br>function TMockInterfacedObject._Release: longint;<br>begin<br>  Result := -1;<br>end;<br><br>end.<br></span><br></div>