Neon.Core.Nullables.pas 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. unit Neon.Core.Nullables;
  2. interface
  3. uses
  4. System.SysUtils, System.Variants, System.Classes, System.Generics.Defaults, System.Rtti,
  5. System.TypInfo, System.JSON;
  6. type
  7. ENullableException = class(Exception);
  8. {$RTTI EXPLICIT FIELDS([vcPrivate]) METHODS([vcPrivate])}
  9. Nullable<T> = record
  10. private
  11. FValue: T;
  12. FHasValue: string;
  13. procedure Clear;
  14. function GetValueType: PTypeInfo;
  15. function GetValue: T;
  16. procedure SetValue(const AValue: T);
  17. function GetHasValue: Boolean;
  18. public
  19. constructor Create(const Value: T); overload;
  20. constructor Create(const Value: Variant); overload;
  21. function Equals(const Value: Nullable<T>): Boolean;
  22. function GetValueOrDefault: T; overload;
  23. function GetValueOrDefault(const Default: T): T; overload;
  24. property HasValue: Boolean read GetHasValue;
  25. function IsNull: Boolean;
  26. property Value: T read GetValue;
  27. class operator Implicit(const Value: Nullable<T>): T;
  28. class operator Implicit(const Value: Nullable<T>): Variant;
  29. class operator Implicit(const Value: Pointer): Nullable<T>;
  30. class operator Implicit(const Value: T): Nullable<T>;
  31. class operator Implicit(const Value: Variant): Nullable<T>;
  32. class operator Equal(const Left, Right: Nullable<T>): Boolean;
  33. class operator NotEqual(const Left, Right: Nullable<T>): Boolean;
  34. end;
  35. NullString = Nullable<string>;
  36. NullBoolean = Nullable<Boolean>;
  37. NullInteger = Nullable<Integer>;
  38. NullInt64 = Nullable<Int64>;
  39. NullDouble = Nullable<Double>;
  40. NullDateTime = Nullable<TDateTime>;
  41. implementation
  42. uses
  43. Neon.Core.Utils;
  44. { Nullable<T> }
  45. constructor Nullable<T>.Create(const Value: T);
  46. var
  47. a: TValue;
  48. begin
  49. FValue := Value;
  50. FHasValue := DefaultTrueBoolStr;
  51. end;
  52. constructor Nullable<T>.Create(const Value: Variant);
  53. begin
  54. if not VarIsNull(Value) and not VarIsEmpty(Value) then
  55. Create(TValue.FromVariant(Value).AsType<T>)
  56. else
  57. Clear;
  58. end;
  59. procedure Nullable<T>.Clear;
  60. begin
  61. FValue := Default(T);
  62. FHasValue := '';
  63. end;
  64. function Nullable<T>.Equals(const Value: Nullable<T>): Boolean;
  65. begin
  66. if HasValue and Value.HasValue then
  67. Result := TEqualityComparer<T>.Default.Equals(Self.Value, Value.Value)
  68. else
  69. Result := HasValue = Value.HasValue;
  70. end;
  71. function Nullable<T>.GetHasValue: Boolean;
  72. begin
  73. Result := FHasValue <> '';
  74. end;
  75. function Nullable<T>.GetValueType: PTypeInfo;
  76. begin
  77. Result := TypeInfo(T);
  78. end;
  79. function Nullable<T>.GetValue: T;
  80. begin
  81. if not HasValue then
  82. raise ENullableException.Create('Nullable type has no value');
  83. Result := FValue;
  84. end;
  85. function Nullable<T>.GetValueOrDefault(const Default: T): T;
  86. begin
  87. if HasValue then
  88. Result := FValue
  89. else
  90. Result := Default;
  91. end;
  92. function Nullable<T>.GetValueOrDefault: T;
  93. begin
  94. Result := GetValueOrDefault(Default(T));
  95. end;
  96. class operator Nullable<T>.Implicit(const Value: Nullable<T>): T;
  97. begin
  98. Result := Value.Value;
  99. end;
  100. class operator Nullable<T>.Implicit(const Value: Nullable<T>): Variant;
  101. begin
  102. if Value.HasValue then
  103. Result := TValue.From<T>(Value.Value).AsVariant
  104. else
  105. Result := Null;
  106. end;
  107. class operator Nullable<T>.Implicit(const Value: Pointer): Nullable<T>;
  108. begin
  109. if Value = nil then
  110. Result.Clear
  111. else
  112. Result := Nullable<T>.Create(T(Value^));
  113. end;
  114. class operator Nullable<T>.Implicit(const Value: T): Nullable<T>;
  115. begin
  116. Result := Nullable<T>.Create(Value);
  117. end;
  118. class operator Nullable<T>.Implicit(const Value: Variant): Nullable<T>;
  119. begin
  120. Result := Nullable<T>.Create(Value);
  121. end;
  122. function Nullable<T>.IsNull: Boolean;
  123. begin
  124. Result := FHasValue = '';
  125. end;
  126. class operator Nullable<T>.Equal(const Left, Right: Nullable<T>): Boolean;
  127. begin
  128. Result := Left.Equals(Right);
  129. end;
  130. class operator Nullable<T>.NotEqual(const Left, Right: Nullable<T>): Boolean;
  131. begin
  132. Result := not Left.Equals(Right);
  133. end;
  134. procedure Nullable<T>.SetValue(const AValue: T);
  135. begin
  136. FValue := AValue;
  137. FHasValue := DefaultTrueBoolStr;
  138. end;
  139. end.