9

I am converting some C# code to Delphi.

In c#, I have Nullabe types as:

System.Nullable<T> variable

or

T? variable

Then, I can use something as:

int?[] arr = new int?[10];

Is there some Delphi VCL equivalent to it?

Luiz Alves
  • 2,575
  • 4
  • 34
  • 75
  • You could use a pointer in delphi. – wimh Apr 17 '16 at 20:17
  • 1
    Use a nullable type. For instance Spring has one. This would never be a VCL type anyway, it's RTL. Try a web search. – David Heffernan Apr 17 '16 at 20:21
  • Did you get what @Wimmel meant about using a pointer? – MartynA Apr 17 '16 at 20:38
  • @ David Heffernan: Thank you for your reposne. I have a small portion of code using Nullable and to use Spring is much more I need for. – Luiz Alves Apr 17 '16 at 20:58
  • @MartynA: No, I did not. – Luiz Alves Apr 17 '16 at 21:00
  • Spring's nullable stands alone I think. In any case you can use the ideas there. Are you prepared to write code or do you want a library recommendation. Did you do any Web search? – David Heffernan Apr 17 '16 at 21:15
  • 1
    There are lots of hits with a google search for *delphi nullable* that also include code. They nearly all work in the same way (with a record) – Sir Rufo Apr 17 '16 at 21:16
  • @David Heffernan, Yes I did. I thought maybe there was a more simple solution. I'd not like write many code. Then, I will look into Spring. Thank you. – Luiz Alves Apr 17 '16 at 21:46
  • You could try to use the nullable types in my dzlib: https://sourceforge.net/p/dzlib/code/HEAD/tree/dzlib/trunk/src/ (those units that start with u_dzNullable* ). Not sure whether that will solve your problem, because I am not familiar with C#'s nullable types. – dummzeuch Apr 18 '16 at 07:47
  • 1
    [Nullable implementation from Allen Bauer's blog](http://blogs.embarcadero.com/abauer/2008/09/18/38869) – Dalija Prasnikar Apr 18 '16 at 08:02
  • @Dalija Prasnikar Thank you. I guess it is a good choice to start with. – Luiz Alves Apr 18 '16 at 12:43
  • Allen Bauer's 2008 Nullable blog post is currently at: [A “Nullable” Post](https://blogs.embarcadero.com/a-nullable-post/) – Paul McGee Mar 27 '21 at 16:37

1 Answers1

3

I found this interesting article about Nullable types and this simplified implementation:

unit Nullable;

{$mode delphi}{$H+}

interface

uses
  Classes, SysUtils;

type
  TNullable<T> = record
  private
    FHasValue: Boolean;
    FValue: T;
    function GetValue: T;
    procedure SetValue(AValue: T);
  public
    procedure Clear;
    property HasValue: Boolean read FHasValue;
    property Value: T read GetValue write SetValue;
    class operator Implicit(A: T): TNullable<T>;
    class operator Implicit(A: Pointer): TNullable<T>;
  end;

implementation

{ TNullable }

function TNullable<T>.GetValue: T;
begin
  if FHasValue then
     Result := FValue
  else
    raise Exception.Create('Variable has no value');
end;

procedure TNullable<T>.SetValue(AValue: T);
begin
  FValue := AValue;
  FHasValue := True;
end;

procedure TNullable<T>.Clear;
begin
  FHasValue := False;
end;

class operator TNullable<T>.Implicit(A: T): TNullable<T>;
begin
  Result.Value := A;
end;

class operator TNullable<T>.Implicit(A: Pointer): TNullable<T>;
begin
  if A = nil then Result.Clear
  else raise Exception.Create('Pointer value not allowed');
end;

end.
Fabrizio
  • 7,603
  • 6
  • 44
  • 104
  • In my simple test, the `Value` or `HasValue` is not initialized, so I would recommend using something else (e.g. delphi-neon) – RaelB Dec 14 '21 at 12:17
  • Aren't [objects fields always initialized](https://stackoverflow.com/a/132770/4528159)? I don't know which is the behavior for generics, but at least `FHasValue` should be initialized – Fabrizio Dec 16 '21 at 10:36
  • procedure TForm1.FPTest; var NS: TNullable; begin ShowMessage('HasValue: ' + BoolToStr(NS.HasValue, True)); ShowMessage('Value: ' + NS.Value.ToString); end; Result: `True`, `Some large number`.. One would expect `HasValue` to be false, and therefore accessing NS.Value should throw an error.. That is what delphi-neon does – RaelB Dec 16 '21 at 10:56
  • You're right, my fault. That's because `TNullable` is a record (and not an object), so it behave like a common base type (like `string`, `integer`...). If you use it as a local variable, it is not automatically initialized. If you place it as a form's field, it will be automatically initialized instead – Fabrizio Dec 16 '21 at 13:14