Skip to content

Commit e2243c1

Browse files
committed
Improving nullability handling in maybe
1 parent c3ade4b commit e2243c1

1 file changed

Lines changed: 36 additions & 19 deletions

File tree

  • CSharpFunctionalExtensions/Maybe

CSharpFunctionalExtensions/Maybe/Maybe.cs

Lines changed: 36 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ namespace CSharpFunctionalExtensions
1515
[System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential)]
1616
public readonly partial struct Maybe<T> : IEquatable<Maybe<T>>, IEquatable<object>, IMaybe<T>
1717
{
18-
1918
private readonly bool _isValueSet;
2019

2120
private readonly T? _value;
@@ -26,7 +25,7 @@ namespace CSharpFunctionalExtensions
2625
/// <exception cref="InvalidOperationException">Maybe has no value.</exception>
2726
public T GetValueOrThrow(string? errorMessage = null)
2827
{
29-
if (_value is null || HasNoValue)
28+
if (HasNoValue)
3029
throw new InvalidOperationException(errorMessage ?? Configuration.NoValueException);
3130

3231
return _value;
@@ -38,20 +37,28 @@ public T GetValueOrThrow(string? errorMessage = null)
3837
/// <exception cref="Exception">Maybe has no value.</exception>
3938
public T GetValueOrThrow(Exception exception)
4039
{
41-
if (_value is null || HasNoValue)
40+
if (HasNoValue)
4241
throw exception;
4342

4443
return _value;
4544
}
4645

47-
public T? GetValueOrDefault(T? defaultValue = default)
46+
public T GetValueOrDefault(T defaultValue)
4847
{
4948
if (HasNoValue)
5049
return defaultValue;
5150

5251
return _value;
5352
}
5453

54+
public T? GetValueOrDefault()
55+
{
56+
if (HasNoValue)
57+
return default;
58+
59+
return _value;
60+
}
61+
5562
/// <summary>
5663
/// Indicates whether the inner value is present and returns the value if it is.
5764
/// </summary>
@@ -76,7 +83,14 @@ public bool TryGetValue(
7683

7784
public static Maybe<T> None => new Maybe<T>();
7885

86+
#if NET5_0_OR_GREATER
87+
[MemberNotNullWhen(true, "_value")]
88+
#endif
7989
public bool HasValue => _isValueSet;
90+
91+
#if NET5_0_OR_GREATER
92+
[MemberNotNullWhen(false, "_value")]
93+
#endif
8094
public bool HasNoValue => !HasValue;
8195

8296
private Maybe(T? value)
@@ -102,7 +116,7 @@ public static implicit operator Maybe<T>(T? value)
102116
return Maybe.From(value);
103117
}
104118

105-
public static implicit operator Maybe<T>(Maybe value) => None;
119+
public static implicit operator Maybe<T>(Maybe _) => None;
106120

107121
public static Maybe<T> From(T? value)
108122
{
@@ -130,13 +144,13 @@ public static async Task<Maybe<T>> From(Func<Task<T?>> valueTaskFunc)
130144
return new Maybe<T>(value);
131145
}
132146

133-
public static bool operator ==(Maybe<T> maybe, T value)
147+
public static bool operator ==(Maybe<T> maybe, T? value)
134148
{
135-
if (value is Maybe<T>)
136-
return maybe.Equals(value);
149+
if (value is Maybe<T> maybeValue)
150+
return maybe.Equals(maybeValue);
137151

138-
if (maybe._value is null || maybe.HasNoValue)
139-
return value is null;
152+
if (maybe.HasNoValue)
153+
return value == null;
140154

141155
return maybe._value.Equals(value);
142156
}
@@ -168,12 +182,15 @@ public static async Task<Maybe<T>> From(Func<Task<T?>> valueTaskFunc)
168182

169183
public override bool Equals(object? obj)
170184
{
171-
if (obj is null)
185+
if (obj == null)
172186
return false;
173-
if (obj is Maybe<T> other)
174-
return Equals(other);
175-
if (obj is T value)
176-
return Equals(value);
187+
188+
if (obj is Maybe<T> otherMaybe)
189+
return Equals(otherMaybe);
190+
191+
if (obj is T otherValue)
192+
return Equals(otherValue);
193+
177194
return false;
178195
}
179196

@@ -182,26 +199,26 @@ public bool Equals(Maybe<T> other)
182199
if (HasNoValue && other.HasNoValue)
183200
return true;
184201

185-
if (_value is null || HasNoValue || other._value is null || other.HasNoValue)
202+
if (HasNoValue || other.HasNoValue)
186203
return false;
187204

188205
return EqualityComparer<T>.Default.Equals(_value, other._value);
189206
}
190207

191208
public override int GetHashCode()
192209
{
193-
if (_value is null || HasNoValue)
210+
if (HasNoValue)
194211
return 0;
195212

196213
return _value.GetHashCode();
197214
}
198215

199216
public override string ToString()
200217
{
201-
if (_value is null || HasNoValue)
218+
if (HasNoValue)
202219
return "No value";
203220

204-
return _value.ToString()!;
221+
return _value.ToString() ?? _value.GetType().Name;
205222
}
206223
}
207224

0 commit comments

Comments
 (0)