Skip to content

Commit 6186c68

Browse files
committed
WIP: Converting Exception params to exceptionCreator funcs.
1 parent 9ee058e commit 6186c68

16 files changed

+118
-77
lines changed

src/GuardClauses/GuardAgainstNullExtensions.cs

Lines changed: 39 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -22,17 +22,19 @@ public static partial class GuardClauseExtensions
2222
/// <param name="input"></param>
2323
/// <param name="parameterName"></param>
2424
/// <param name="message">Optional. Custom error message</param>
25-
/// <param name="exception"></param>
25+
/// <param name="exceptionCreator"></param>
2626
/// <returns><paramref name="input" /> if the value is not null.</returns>
2727
/// <exception cref="Exception"></exception>
2828
public static T Null<T>(this IGuardClause guardClause,
2929
[NotNull][ValidatedNotNull]T? input,
3030
[CallerArgumentExpression("input")] string? parameterName = null,
3131
string? message = null,
32-
Exception? exception = null)
32+
Func<Exception>? exceptionCreator = null)
3333
{
3434
if (input is null)
3535
{
36+
Exception? exception = exceptionCreator?.Invoke();
37+
3638
if (string.IsNullOrEmpty(message))
3739
{
3840
throw exception ?? new ArgumentNullException(parameterName);
@@ -51,17 +53,19 @@ public static T Null<T>(this IGuardClause guardClause,
5153
/// <param name="input"></param>
5254
/// <param name="parameterName"></param>
5355
/// <param name="message">Optional. Custom error message</param>
54-
/// <param name="exception"></param>
56+
/// <param name="exceptionCreator"></param>
5557
/// <returns><paramref name="input" /> if the value is not null.</returns>
5658
/// <exception cref="Exception"></exception>
5759
public static T Null<T>(this IGuardClause guardClause,
5860
[NotNull][ValidatedNotNull]T? input,
5961
[CallerArgumentExpression("input")] string? parameterName = null,
6062
string? message = null,
61-
Exception? exception = null) where T : struct
63+
Func<Exception>? exceptionCreator = null) where T : struct
6264
{
6365
if (input is null)
6466
{
67+
Exception? exception = exceptionCreator?.Invoke();
68+
6569
if (string.IsNullOrEmpty(message))
6670
{
6771
throw exception ?? new ArgumentNullException(parameterName);
@@ -80,7 +84,7 @@ public static T Null<T>(this IGuardClause guardClause,
8084
/// <param name="input"></param>
8185
/// <param name="parameterName"></param>
8286
/// <param name="message">Optional. Custom error message</param>
83-
/// <param name="exception"></param>
87+
/// <param name="exceptionCreator"></param>
8488
/// <returns><paramref name="input" /> if the value is not an empty string or null.</returns>
8589
/// <exception cref="ArgumentNullException"></exception>
8690
/// <exception cref="ArgumentException"></exception>
@@ -89,12 +93,13 @@ public static string NullOrEmpty(this IGuardClause guardClause,
8993
[NotNull][ValidatedNotNull] string? input,
9094
[CallerArgumentExpression("input")] string? parameterName = null,
9195
string? message = null,
92-
Exception? exception = null)
96+
Func<Exception>? exceptionCreator = null)
9397
{
94-
Guard.Against.Null(input, parameterName, message, exception);
98+
Guard.Against.Null(input, parameterName, message, exceptionCreator);
9599
if (input == string.Empty)
96100
{
97-
throw exception ?? new ArgumentException(message ?? $"Required input {parameterName} was empty.", parameterName);
101+
throw exceptionCreator?.Invoke() ??
102+
new ArgumentException(message ?? $"Required input {parameterName} was empty.", parameterName);
98103
}
99104

100105
return input;
@@ -108,20 +113,22 @@ public static string NullOrEmpty(this IGuardClause guardClause,
108113
/// <param name="input"></param>
109114
/// <param name="parameterName"></param>
110115
/// <param name="message">Optional. Custom error message</param>
111-
/// <param name="exception"></param>
116+
/// <param name="exceptionCreator"></param>
112117
/// <returns><paramref name="input" /> if the value is not an empty guid or null.</returns>
113118
/// <exception cref="ArgumentNullException"></exception>
114119
/// <exception cref="ArgumentException"></exception>
115120
/// <exception cref="Exception"></exception>
116121
public static Guid NullOrEmpty(this IGuardClause guardClause,
117122
[NotNull][ValidatedNotNull] Guid? input,
118123
[CallerArgumentExpression("input")] string? parameterName = null,
119-
string? message = null, Exception? exception = null)
124+
string? message = null,
125+
Func<Exception>? exceptionCreator = null)
120126
{
121-
Guard.Against.Null(input, parameterName, message, exception);
127+
Guard.Against.Null(input, parameterName, message, exceptionCreator);
122128
if (input == Guid.Empty)
123129
{
124-
throw exception ?? new ArgumentException(message ?? $"Required input {parameterName} was empty.", parameterName);
130+
throw exceptionCreator?.Invoke() ??
131+
new ArgumentException(message ?? $"Required input {parameterName} was empty.", parameterName);
125132
}
126133

127134
return input.Value;
@@ -135,25 +142,27 @@ public static Guid NullOrEmpty(this IGuardClause guardClause,
135142
/// <param name="input"></param>
136143
/// <param name="parameterName"></param>
137144
/// <param name="message">Optional. Custom error message</param>
138-
/// <param name="exception"></param>
145+
/// <param name="exceptionCreator"></param>
139146
/// <returns><paramref name="input" /> if the value is not an empty enumerable or null.</returns>
140147
/// <exception cref="ArgumentNullException"></exception>
141148
/// <exception cref="ArgumentException"></exception>
142149
/// <exception cref="Exception"></exception>
143150
public static IEnumerable<T> NullOrEmpty<T>(this IGuardClause guardClause,
144151
[NotNull][ValidatedNotNull] IEnumerable<T>? input,
145152
[CallerArgumentExpression("input")] string? parameterName = null,
146-
string? message = null, Exception? exception = null)
153+
string? message = null,
154+
Func<Exception>? exceptionCreator = null)
147155
{
148-
Guard.Against.Null(input, parameterName, message, exception);
156+
Guard.Against.Null(input, parameterName, message, exceptionCreator: exceptionCreator);
149157

150158
if (input is Array and { Length: 0 } //Try checking first with pattern matching because it's faster than TryGetNonEnumeratedCount on Array
151159
#if NET6_0_OR_GREATER
152160
|| (input.TryGetNonEnumeratedCount(out var count) && count == 0)
153161
#endif
154162
|| !input.Any())
155163
{
156-
throw exception ?? new ArgumentException(message ?? $"Required input {parameterName} was empty.", parameterName);
164+
throw exceptionCreator?.Invoke() ??
165+
new ArgumentException(message ?? $"Required input {parameterName} was empty.", parameterName);
157166
}
158167

159168
return input;
@@ -167,20 +176,22 @@ public static IEnumerable<T> NullOrEmpty<T>(this IGuardClause guardClause,
167176
/// <param name="input"></param>
168177
/// <param name="parameterName"></param>
169178
/// <param name="message">Optional. Custom error message</param>
170-
/// <param name="exception"></param>
179+
/// <param name="exceptionCreator"></param>
171180
/// <returns><paramref name="input" /> if the value is not an empty or whitespace string.</returns>
172181
/// <exception cref="ArgumentNullException"></exception>
173182
/// <exception cref="ArgumentException"></exception>
174183
/// <exception cref="Exception"></exception>
175184
public static string NullOrWhiteSpace(this IGuardClause guardClause,
176185
[NotNull][ValidatedNotNull] string? input,
177186
[CallerArgumentExpression("input")] string? parameterName = null,
178-
string? message = null, Exception? exception = null)
187+
string? message = null,
188+
Func<Exception>? exceptionCreator = null)
179189
{
180-
Guard.Against.NullOrEmpty(input, parameterName, message, exception);
190+
Guard.Against.NullOrEmpty(input, parameterName, message, exceptionCreator);
181191
if (String.IsNullOrWhiteSpace(input))
182192
{
183-
throw exception ?? new ArgumentException(message ?? $"Required input {parameterName} was empty.", parameterName);
193+
throw exceptionCreator?.Invoke() ??
194+
new ArgumentException(message ?? $"Required input {parameterName} was empty.", parameterName);
184195
}
185196

186197
return input;
@@ -193,19 +204,20 @@ public static string NullOrWhiteSpace(this IGuardClause guardClause,
193204
/// <param name="input"></param>
194205
/// <param name="parameterName"></param>
195206
/// <param name="message">Optional. Custom error message</param>
196-
/// <param name="exception"></param>
207+
/// <param name="exceptionCreator"></param>
197208
/// <returns><paramref name="input" /> if the value is not default for that type.</returns>
198209
/// <exception cref="ArgumentException"></exception>
199210
/// <exception cref="Exception"></exception>
200211
public static T Default<T>(this IGuardClause guardClause,
201212
[AllowNull, NotNull]T input,
202213
[CallerArgumentExpression("input")] string? parameterName = null,
203214
string? message = null,
204-
Exception? exception = null)
215+
Func<Exception>? exceptionCreator = null)
205216
{
206217
if (EqualityComparer<T>.Default.Equals(input, default(T)!) || input is null)
207218
{
208-
throw exception ?? new ArgumentException(message ?? $"Parameter [{parameterName}] is default value for type {typeof(T).Name}", parameterName);
219+
throw exceptionCreator?.Invoke() ??
220+
new ArgumentException(message ?? $"Parameter [{parameterName}] is default value for type {typeof(T).Name}", parameterName);
209221
}
210222

211223
return input;
@@ -221,7 +233,7 @@ public static T Default<T>(this IGuardClause guardClause,
221233
/// <param name="parameterName"></param>
222234
/// <param name="predicate"></param>
223235
/// <param name="message">Optional. Custom error message</param>
224-
/// <param name="exception"></param>
236+
/// <param name="exceptionCreator"></param>
225237
/// <typeparam name="T"></typeparam>
226238
/// <returns></returns>
227239
/// <exception cref="ArgumentException"></exception>
@@ -232,10 +244,10 @@ public static T NullOrInvalidInput<T>(this IGuardClause guardClause,
232244
string parameterName,
233245
Func<T, bool> predicate,
234246
string? message = null,
235-
Exception? exception = null)
247+
Func<Exception>? exceptionCreator = null)
236248
{
237-
Guard.Against.Null(input, parameterName, message, exception);
249+
Guard.Against.Null(input, parameterName, message, exceptionCreator: exceptionCreator);
238250

239-
return Guard.Against.InvalidInput(input, parameterName, predicate, message, exception);
251+
return Guard.Against.InvalidInput(input, parameterName, predicate, message, exceptionCreator?.Invoke());
240252
}
241253
}

src/GuardClauses/GuardAgainstOutOfRangeExtensions.cs

Lines changed: 24 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ public static partial class GuardClauseExtensions
1818
/// <param name="maxLength"></param>
1919
/// <param name="parameterName"></param>
2020
/// <param name="message">Optional. Custom error message</param>
21-
/// <param name="exception"></param>
21+
/// <param name="exceptionCreator"></param>
2222
/// <returns><paramref name="input" /> if the value is not negative.</returns>
2323
/// <exception cref="ArgumentException"></exception>
2424
/// <exception cref="Exception"></exception>
@@ -28,12 +28,12 @@ public static string LengthOutOfRange(this IGuardClause guardClause,
2828
int maxLength,
2929
[CallerArgumentExpression("input")] string? parameterName = null,
3030
string? message = null,
31-
Exception? exception = null)
31+
Func<Exception>? exceptionCreator = null)
3232
{
3333
Guard.Against.Negative<int>(maxLength - minLength, parameterName: "min or max length",
34-
message: "Min length must be equal or less than max length.", exception: exception);
35-
Guard.Against.StringTooShort(input, minLength, nameof(minLength), exception: exception);
36-
Guard.Against.StringTooLong(input, maxLength, nameof(maxLength), exception: exception);
34+
message: "Min length must be equal or less than max length.", exception: exceptionCreator?.Invoke());
35+
Guard.Against.StringTooShort(input, minLength, nameof(minLength), exception: exceptionCreator?.Invoke());
36+
Guard.Against.StringTooLong(input, maxLength, nameof(maxLength), exception: exceptionCreator?.Invoke());
3737

3838
return input;
3939
}
@@ -46,18 +46,19 @@ public static string LengthOutOfRange(this IGuardClause guardClause,
4646
/// <param name="input"></param>
4747
/// <param name="parameterName"></param>
4848
/// <param name="message">Optional. Custom error message</param>
49-
/// <param name="exception"></param>
49+
/// <param name="exceptionCreator"></param>
5050
/// <returns><paramref name="input" /> if the value is not out of range.</returns>
5151
/// <exception cref="InvalidEnumArgumentException"></exception>
5252
/// <exception cref="Exception"></exception>
5353
public static int EnumOutOfRange<T>(this IGuardClause guardClause,
5454
int input,
5555
[CallerArgumentExpression("input")] string? parameterName = null,
5656
string? message = null,
57-
Exception? exception = null) where T : struct, Enum
57+
Func<Exception>? exceptionCreator = null) where T : struct, Enum
5858
{
5959
if (!Enum.IsDefined(typeof(T), input))
6060
{
61+
var exception = exceptionCreator?.Invoke();
6162
if (string.IsNullOrEmpty(message))
6263
{
6364
throw exception ?? new InvalidEnumArgumentException(parameterName, input, typeof(T));
@@ -76,18 +77,19 @@ public static int EnumOutOfRange<T>(this IGuardClause guardClause,
7677
/// <param name="input"></param>
7778
/// <param name="parameterName"></param>
7879
/// /// <param name="message">Optional. Custom error message</param>
79-
/// <param name="exception"></param>
80+
/// <param name="exceptionCreator"></param>
8081
/// <returns><paramref name="input" /> if the value is not out of range.</returns>
8182
/// <exception cref="InvalidEnumArgumentException"></exception>
8283
/// <exception cref="Exception"></exception>
8384
public static T EnumOutOfRange<T>(this IGuardClause guardClause,
8485
T input,
8586
[CallerArgumentExpression("input")] string? parameterName = null,
8687
string? message = null,
87-
Exception? exception = null) where T : struct, Enum
88+
Func<Exception>? exceptionCreator = null) where T : struct, Enum
8889
{
8990
if (!Enum.IsDefined(typeof(T), input))
9091
{
92+
var exception = exceptionCreator?.Invoke();
9193
if (string.IsNullOrEmpty(message))
9294
{
9395
throw exception ?? new InvalidEnumArgumentException(parameterName, Convert.ToInt32(input), typeof(T));
@@ -99,15 +101,16 @@ public static T EnumOutOfRange<T>(this IGuardClause guardClause,
99101
}
100102

101103
/// <summary>
102-
/// Throws an <see cref="ArgumentOutOfRangeException" /> or a custom <see cref="Exception" /> if any <paramref name="input"/>'s item is less than <paramref name="rangeFrom"/> or greater than <paramref name="rangeTo"/>.
104+
/// Throws an <see cref="ArgumentOutOfRangeException" /> or a custom <see cref="Exception" /> if
105+
/// any <paramref name="input"/>'s item is less than <paramref name="rangeFrom"/> or greater than <paramref name="rangeTo"/>.
103106
/// </summary>
104107
/// <param name="guardClause"></param>
105108
/// <param name="input"></param>
106109
/// <param name="parameterName"></param>
107110
/// <param name="rangeFrom"></param>
108111
/// <param name="rangeTo"></param>
109112
/// <param name="message">Optional. Custom error message</param>
110-
/// <param name="exception"></param>
113+
/// <param name="exceptionCreator"></param>
111114
/// <returns><paramref name="input" /> if any item is not out of range.</returns>
112115
/// <exception cref="ArgumentException"></exception>
113116
/// <exception cref="ArgumentOutOfRangeException"></exception>
@@ -117,20 +120,22 @@ public static IEnumerable<T> OutOfRange<T>(this IGuardClause guardClause,
117120
string parameterName,
118121
T rangeFrom, T rangeTo,
119122
string? message = null,
120-
Exception? exception = null) where T : IComparable, IComparable<T>
123+
Func<Exception>? exceptionCreator = null) where T : IComparable, IComparable<T>
121124
{
122125
if (rangeFrom.CompareTo(rangeTo) > 0)
123126
{
124-
throw new ArgumentException(message ?? $"{nameof(rangeFrom)} should be less or equal than {nameof(rangeTo)}", parameterName);
127+
throw exceptionCreator?.Invoke() ??
128+
new ArgumentException(message ?? $"{nameof(rangeFrom)} should be less or equal than {nameof(rangeTo)}", parameterName);
125129
}
126130

127131
if (input.Any(x => x.CompareTo(rangeFrom) < 0 || x.CompareTo(rangeTo) > 0))
128132
{
129133
if (string.IsNullOrEmpty(message))
130134
{
131-
throw exception ?? new ArgumentOutOfRangeException(parameterName, message ?? $"Input {parameterName} had out of range item(s)");
135+
throw exceptionCreator?.Invoke() ??
136+
new ArgumentOutOfRangeException(parameterName, message ?? $"Input {parameterName} had out of range item(s)");
132137
}
133-
throw exception ?? new ArgumentOutOfRangeException(parameterName, message);
138+
throw exceptionCreator?.Invoke() ?? new ArgumentOutOfRangeException(parameterName, message);
134139
}
135140

136141
return input;
@@ -154,7 +159,7 @@ public static DateTime NullOrOutOfSQLDateRange(this IGuardClause guardClause,
154159
[CallerArgumentExpression("input")] string? parameterName = null,
155160
string? message = null, Exception? exception = null)
156161
{
157-
guardClause.Null(input, nameof(input),exception: exception);
162+
guardClause.Null(input, nameof(input), exceptionCreator: () =>exception);
158163
return OutOfSQLDateRange(guardClause, input.Value, parameterName, message, exception);
159164
}
160165

@@ -228,8 +233,8 @@ public static T NullOrOutOfRange<T>(this IGuardClause guardClause,
228233
[NotNull][ValidatedNotNull] T rangeTo,
229234
string? message = null, Exception? exception = null) where T : IComparable<T>
230235
{
231-
guardClause.Null(input, nameof(input),exception: exception);
232-
return NullOrOutOfRangeInternal(guardClause, input, parameterName, rangeFrom, rangeTo, message,exception);
236+
guardClause.Null(input, nameof(input),exceptionCreator: () => exception);
237+
return NullOrOutOfRangeInternal(guardClause, input, parameterName, rangeFrom, rangeTo, message, exception);
233238
}
234239

235240
/// <summary>
@@ -255,7 +260,7 @@ public static T NullOrOutOfRange<T>(this IGuardClause guardClause,
255260
[NotNull][ValidatedNotNull] T rangeTo,
256261
string? message = null, Exception? exception = null) where T : struct, IComparable<T>
257262
{
258-
guardClause.Null(input, nameof(input), exception: exception);
263+
guardClause.Null(input, nameof(input), exceptionCreator: () => exception);
259264
return NullOrOutOfRangeInternal<T>(guardClause, input.Value, parameterName, rangeFrom, rangeTo, message, exception);
260265
}
261266

test/GuardClauses.UnitTests/GuardAgainstDefault.cs

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,16 @@ public void ThrowsGivenDefaultValue()
3030
public void ThrowsCustomExceptionWhenSuppliedGivenDefaultValue()
3131
{
3232
Exception customException = new Exception();
33-
Assert.Throws<Exception>( () => Guard.Against.Default(default(string), "string", exception: customException));
34-
Assert.Throws<Exception>( () => Guard.Against.Default(default(int), "int", exception: customException));
35-
Assert.Throws<Exception>(() => Guard.Against.Default(default(Guid), "guid", exception: customException));
36-
Assert.Throws<Exception>( () => Guard.Against.Default(default(DateTime), "datetime", exception: customException));
37-
Assert.Throws<Exception>( () => Guard.Against.Default(default(object), "object", exception: customException));
33+
Assert.Throws<Exception>( () => Guard.Against.Default(default(string), "string",
34+
exceptionCreator: () => customException));
35+
Assert.Throws<Exception>( () => Guard.Against.Default(default(int), "int",
36+
exceptionCreator: () => customException));
37+
Assert.Throws<Exception>(() => Guard.Against.Default(default(Guid), "guid",
38+
exceptionCreator: () => customException));
39+
Assert.Throws<Exception>( () => Guard.Against.Default(default(DateTime), "datetime",
40+
exceptionCreator: () => customException));
41+
Assert.Throws<Exception>( () => Guard.Against.Default(default(object), "object",
42+
exceptionCreator: () => customException));
3843
}
3944

4045
[Theory]

0 commit comments

Comments
 (0)