@@ -52,6 +52,11 @@ public static class Luhn
52
52
/// </summary>
53
53
private const int Modulus = 10 ;
54
54
55
+ /// <summary>
56
+ /// Represents the ASCII code for the character '0'.
57
+ /// </summary>
58
+ private const int AsciiCodeForZero = 48 ;
59
+
55
60
#if NET8_0_OR_GREATER
56
61
/// <summary>
57
62
/// Computes the Luhn check digit
@@ -63,7 +68,7 @@ public static class Luhn
63
68
[ SuppressMessage ( "ReSharper" , "UnusedMember.Global" ) ]
64
69
[ SuppressMessage ( "ReSharper" , "HeapView.ObjectAllocation" ) ]
65
70
public static byte ComputeLuhnCheckDigit ( this ReadOnlySpan < char > number ) =>
66
- ( byte ) ( ( Modulus - number . IsNumber ( ) . GetDigits ( ) . DoubleEverySecondDigit ( false ) . SumDigits ( ) ) % Modulus ) ;
71
+ ( byte ) ( ( Modulus - number . ValidateAndTrimNumber ( ) . GetDigits ( ) . DoubleEverySecondDigit ( false ) . SumDigits ( ) ) % Modulus ) ;
67
72
#endif
68
73
69
74
/// <summary>
@@ -79,7 +84,7 @@ public static byte ComputeLuhnCheckDigit(this string number) =>
79
84
#if NET8_0_OR_GREATER
80
85
number . AsSpan ( ) . ComputeLuhnCheckDigit ( ) ;
81
86
#else
82
- ( byte ) ( ( Modulus - number . IsNumber ( ) . GetDigits ( ) . DoubleEverySecondDigit ( false ) . SumDigits ( ) ) % Modulus ) ;
87
+ ( byte ) ( ( Modulus - number . ValidateAndTrimNumber ( ) . GetDigits ( ) . DoubleEverySecondDigit ( false ) . SumDigits ( ) ) % Modulus ) ;
83
88
#endif
84
89
85
90
#if NET8_0_OR_GREATER
@@ -123,21 +128,6 @@ public static string ComputeLuhnNumber(this string number)
123
128
}
124
129
125
130
#if NET8_0_OR_GREATER
126
- /// <summary>
127
- /// Checks whether the Luhn Number is valid
128
- /// </summary>
129
- /// <param name="luhnNumber">An identification number w/ check digit (Luhn Number).</param>
130
- /// <returns><see langword="true" /> if the <paramref name="luhnNumber"/> is valid;
131
- /// otherwise <see langword="false" /></returns>
132
- /// <exception cref="ArgumentException"><paramref name="luhnNumber"/> is not valid.
133
- /// It contains none-numeric characters.</exception>
134
- /// <remarks>The check digit must be at the end of the <paramref name="luhnNumber"/>
135
- /// (on the right side).</remarks>
136
- [ SuppressMessage ( "ReSharper" , "UnusedMember.Global" ) ]
137
- [ SuppressMessage ( "ReSharper" , "HeapView.ObjectAllocation" ) ]
138
- [ Obsolete ( "Use the IsValidLuhnNumber method instead." , false ) ]
139
- public static bool IsValid ( this ReadOnlySpan < char > luhnNumber ) => luhnNumber . IsValidLuhnNumber ( ) ;
140
-
141
131
/// <summary>
142
132
/// Checks whether the Luhn Number is valid
143
133
/// </summary>
@@ -151,24 +141,9 @@ public static string ComputeLuhnNumber(this string number)
151
141
[ SuppressMessage ( "ReSharper" , "UnusedMember.Global" ) ]
152
142
[ SuppressMessage ( "ReSharper" , "HeapView.ObjectAllocation" ) ]
153
143
public static bool IsValidLuhnNumber ( this ReadOnlySpan < char > luhnNumber ) =>
154
- luhnNumber . IsNumber ( ) . GetDigits ( ) . DoubleEverySecondDigit ( true ) . SumDigits ( ) == 0 ;
144
+ luhnNumber . ValidateAndTrimNumber ( ) . GetDigits ( ) . DoubleEverySecondDigit ( true ) . SumDigits ( ) == 0 ;
155
145
#endif
156
146
157
- /// <summary>
158
- /// Checks whether the Luhn Number is valid
159
- /// </summary>
160
- /// <param name="luhnNumber">An identification number w/ check digit (Luhn Number).</param>
161
- /// <returns><see langword="true" /> if the <paramref name="luhnNumber"/> is valid;
162
- /// otherwise <see langword="false" /></returns>
163
- /// <exception cref="ArgumentException"><paramref name="luhnNumber"/> is not valid.
164
- /// It contains none-numeric characters.</exception>
165
- /// <remarks>The check digit must be at the end of the <paramref name="luhnNumber"/>
166
- /// (on the right side).</remarks>
167
- [ SuppressMessage ( "ReSharper" , "UnusedMember.Global" ) ]
168
- [ SuppressMessage ( "ReSharper" , "HeapView.ObjectAllocation" ) ]
169
- [ Obsolete ( "Use the IsValidLuhnNumber method instead." , false ) ]
170
- public static bool IsValid ( this string luhnNumber ) => luhnNumber . IsValidLuhnNumber ( ) ;
171
-
172
147
/// <summary>
173
148
/// Checks whether the Luhn Number is valid
174
149
/// </summary>
@@ -185,27 +160,10 @@ public static bool IsValidLuhnNumber(this string luhnNumber) =>
185
160
#if NET8_0_OR_GREATER
186
161
luhnNumber . AsSpan ( ) . IsValidLuhnNumber ( ) ;
187
162
#else
188
- luhnNumber . IsNumber ( ) . GetDigits ( ) . DoubleEverySecondDigit ( true ) . SumDigits ( ) == 0 ;
163
+ luhnNumber . ValidateAndTrimNumber ( ) . GetDigits ( ) . DoubleEverySecondDigit ( true ) . SumDigits ( ) == 0 ;
189
164
#endif
190
165
191
166
#if NET8_0_OR_GREATER
192
- /// <summary>
193
- /// Checks whether the concatenation of number and corresponding Luhn check digit is valid
194
- /// </summary>
195
- /// <param name="number">Identification number w/o Luhn check digit</param>
196
- /// <param name="checkDigit">The Luhn check digit</param>
197
- /// <returns><see langword="true" /> if the <paramref name="number"/> is valid;
198
- /// otherwise <see langword="false" /></returns>
199
- /// <exception cref="ArgumentException"><paramref name="number"/> is not valid.
200
- /// It contains none-numeric characters.</exception>
201
- /// <exception cref="ArgumentOutOfRangeException">The <paramref name="checkDigit"/> value is greater than 9.
202
- /// The <paramref name="checkDigit"/> value must be between 0 and 9.</exception>
203
- [ SuppressMessage ( "ReSharper" , "UnusedMember.Global" ) ]
204
- [ SuppressMessage ( "ReSharper" , "HeapView.ObjectAllocation" ) ]
205
- [ Obsolete ( "Use the IsValidLuhnCheckDigit method instead." , false ) ]
206
- public static bool IsValid ( this ReadOnlySpan < char > number , byte checkDigit ) =>
207
- checkDigit . IsValidLuhnCheckDigit ( number ) ;
208
-
209
167
/// <summary>
210
168
/// Checks whether the concatenation of number and corresponding Luhn check digit is valid
211
169
/// </summary>
@@ -231,29 +189,13 @@ public static bool IsValidLuhnCheckDigit(this byte checkDigit, ReadOnlySpan<char
231
189
232
190
return string . Concat ( number . Trim ( ) , checkDigit . ToString ( CultureInfo . InvariantCulture ) )
233
191
. AsSpan ( )
234
- . IsNumber ( )
192
+ . ValidateAndTrimNumber ( )
235
193
. GetDigits ( )
236
194
. DoubleEverySecondDigit ( true )
237
195
. SumDigits ( ) == 0 ;
238
196
}
239
197
#endif
240
198
241
- /// <summary>
242
- /// Checks whether the concatenation of number and corresponding Luhn check digit is valid
243
- /// </summary>
244
- /// <param name="number">Identification number w/o Luhn check digit</param>
245
- /// <param name="checkDigit">The Luhn check digit</param>
246
- /// <returns><see langword="true" /> if the <paramref name="number"/> is valid;
247
- /// otherwise <see langword="false" /></returns>
248
- /// <exception cref="ArgumentException"><paramref name="number"/> is not valid.
249
- /// It contains none-numeric characters.</exception>
250
- /// <exception cref="ArgumentOutOfRangeException">The <paramref name="checkDigit"/> value is greater than 9.
251
- /// The <paramref name="checkDigit"/> value must be between 0 and 9.</exception>
252
- [ SuppressMessage ( "ReSharper" , "UnusedMember.Global" ) ]
253
- [ SuppressMessage ( "ReSharper" , "HeapView.ObjectAllocation" ) ]
254
- [ Obsolete ( "Use the IsValidLuhnCheckDigit method instead." , false ) ]
255
- public static bool IsValid ( this string number , byte checkDigit ) => checkDigit . IsValidLuhnCheckDigit ( number ) ;
256
-
257
199
/// <summary>
258
200
/// Checks whether the concatenation of number and corresponding Luhn check digit is valid
259
201
/// </summary>
@@ -285,7 +227,7 @@ public static bool IsValidLuhnCheckDigit(this byte checkDigit, string number)
285
227
"{0}{1}" ,
286
228
number . Trim ( ) ,
287
229
checkDigit . ToString ( CultureInfo . InvariantCulture ) )
288
- . IsNumber ( )
230
+ . ValidateAndTrimNumber ( )
289
231
. GetDigits ( )
290
232
. DoubleEverySecondDigit ( true )
291
233
. SumDigits ( ) == 0 ;
@@ -357,12 +299,12 @@ public static string ConvertAlphaNumericToNumeric(this string alphaNumeric)
357
299
#endif
358
300
359
301
/// <summary>
360
- /// Doubling of every second digit.
302
+ /// Doubles every second digit of the <paramref name="digits"/> enumeration .
361
303
/// </summary>
362
304
/// <param name="digits">The digits represent a number w/ or w/o check digit.</param>
363
305
/// <param name="forValidation"><see langword="true"/> if the <paramref name="digits"/> represent
364
306
/// a Luhn number including a check digit; otherwise <see langword="false"/></param>
365
- /// <returns></returns>
307
+ /// <returns>Enumeration of digits </returns>
366
308
private static IEnumerable < uint > DoubleEverySecondDigit ( this IEnumerable < uint > digits , bool forValidation )
367
309
{
368
310
int index = 0 ;
@@ -399,7 +341,7 @@ private static IEnumerable<uint> DoubleEverySecondDigit(this IEnumerable<uint> d
399
341
/// <param name="number">An identification number</param>
400
342
/// <returns>The trimmed identification number if valid</returns>
401
343
/// <exception cref="ArgumentException"><paramref name="number"/> is not a valid number</exception>
402
- private static string IsNumber ( this string number )
344
+ private static string ValidateAndTrimNumber ( this string number )
403
345
{
404
346
string trimmedNumber = number ? . Trim ( ) ;
405
347
if ( string . IsNullOrWhiteSpace ( trimmedNumber ) || ! Regex . IsMatch ( trimmedNumber , @"^\d+$" ) )
@@ -418,7 +360,7 @@ private static string IsNumber(this string number)
418
360
/// <param name="number">An identification number</param>
419
361
/// <returns>The trimmed identification number if valid</returns>
420
362
/// <exception cref="ArgumentException"><paramref name="number"/> is not a valid number</exception>
421
- private static ReadOnlySpan < char > IsNumber ( this ReadOnlySpan < char > number )
363
+ private static ReadOnlySpan < char > ValidateAndTrimNumber ( this ReadOnlySpan < char > number )
422
364
{
423
365
var trimmedNumber = number . Trim ( ) ;
424
366
if ( trimmedNumber . Length == 0 || ! trimmedNumber . IsDigits ( ) )
@@ -460,7 +402,7 @@ private static IEnumerable<uint> GetDigits(this ReadOnlySpan<char> number)
460
402
uint [ ] digits = new uint [ number . Length ] ;
461
403
for ( int i = 0 ; i < number . Length ; i ++ )
462
404
{
463
- digits [ number . Length - i - 1 ] = ( uint ) number [ i ] - 48 ;
405
+ digits [ number . Length - i - 1 ] = ( uint ) number [ i ] - AsciiCodeForZero ;
464
406
}
465
407
466
408
return digits ;
@@ -470,7 +412,7 @@ private static IEnumerable<uint> GetDigits(this string number)
470
412
{
471
413
for ( int i = number . Length - 1 ; i >= 0 ; i -- )
472
414
{
473
- yield return ( uint ) number [ i ] - 48 ;
415
+ yield return ( uint ) number [ i ] - AsciiCodeForZero ;
474
416
}
475
417
}
476
418
#endif
0 commit comments