Skip to content

Commit bd206c0

Browse files
Allow for null value comparison without throwing.
1 parent 304bb93 commit bd206c0

2 files changed

Lines changed: 37 additions & 13 deletions

File tree

Source/StringComparable.cs

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -13,21 +13,17 @@ public readonly struct StringComparable
1313
/// <summary>
1414
/// Constructs a StringComparable using the provided string and comparison type.
1515
/// </summary>
16-
/// <exception cref="ArgumentException"><paramref name="segment"/> does not contain a value (is default).</exception>
1716
public StringComparable(StringSegment segment, StringComparison type)
1817
{
19-
if (!segment.HasValue) throw new ArgumentException("The provided segment must have a value.", nameof(segment));
2018
Segment = segment;
2119
Type = type;
2220
}
2321

2422
/// <summary>
2523
/// Constructs a StringComparable using the provided string and comparison type.
2624
/// </summary>
27-
/// <exception cref="ArgumentNullException"><paramref name="value"/> is null</exception>
28-
public StringComparable(string value, StringComparison type)
25+
public StringComparable(string? value, StringComparison type)
2926
{
30-
if (value is null) throw new ArgumentNullException(nameof(value));
3127
Segment = value;
3228
Type = type;
3329
}
@@ -52,7 +48,7 @@ public StringComparable(string value, StringComparison type)
5248
/// </summary>
5349
/// <returns>true if the value of <paramref name="other"/> matches; otherwise false. </returns>
5450
public bool Equals(string? other)
55-
=> other is not null && Segment.Equals(other, Type);
51+
=> Segment.Equals(other, Type);
5652

5753
/// <inheritdoc cref="Equals(string?)"/>
5854
public bool Equals(ReadOnlySpan<char> other)
@@ -174,41 +170,41 @@ public static class StringComparableExtensions
174170
/// Prepares a string for a specific StringComparison operation.
175171
/// </summary>
176172
/// <inheritdoc cref="AsCaseInsensitive(string)"/>
177-
public static StringComparable AsComparable(this string source, StringComparison type)
173+
public static StringComparable AsComparable(this string? source, StringComparison type)
178174
=> new(source, type);
179175

180176
/// <summary>
181177
/// Prepares a string to be case insensitive when comparing equality.
182178
/// </summary>
183179
/// <returns>A StringComparable that can be compared (== or !=) against other StringComparables, SpanComparables, strings, and ReadOnlySpan&lt;char&gt;.</returns>
184-
public static StringComparable AsCaseInsensitive(this string source)
180+
public static StringComparable AsCaseInsensitive(this string? source)
185181
=> new(source, StringComparison.OrdinalIgnoreCase);
186182

187183
/// <summary>
188184
/// Prepares a string to be invariant culture and case insensitive when comparing equality.
189185
/// </summary>
190186
/// <inheritdoc cref="AsCaseInsensitive(string)"/>
191-
public static StringComparable AsCaseInsensitiveInvariantCulture(this string source)
187+
public static StringComparable AsCaseInsensitiveInvariantCulture(this string? source)
192188
=> new(source, StringComparison.InvariantCultureIgnoreCase);
193189

194190
/// <summary>
195191
/// Prepares a string to be invariant culture and case insensitive when comparing equality.
196192
/// </summary>
197193
/// <inheritdoc cref="AsCaseInsensitive(string)"/>
198-
public static StringComparable AsCaseInsensitiveCurrentCulture(this string source)
194+
public static StringComparable AsCaseInsensitiveCurrentCulture(this string? source)
199195
=> new(source, StringComparison.CurrentCultureIgnoreCase);
200196

201197
/// <summary>
202198
/// Prepares a string to be current culture and case sensitive when comparing equality.
203199
/// </summary>
204200
/// <inheritdoc cref="AsCaseInsensitive(string)"/>
205-
public static StringComparable AsCurrentCulture(this string source)
201+
public static StringComparable AsCurrentCulture(this string? source)
206202
=> new(source, StringComparison.CurrentCulture);
207203

208204
/// <summary>
209205
/// Prepares a string to be invariant culture and case sensitive when comparing equality.
210206
/// </summary>
211-
public static StringComparable AsInvariantCulture(this string source)
207+
public static StringComparable AsInvariantCulture(this string? source)
212208
=> new(source, StringComparison.InvariantCulture);
213209

214210
/// <summary>

Tests/ComparableTests.cs

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,10 @@ namespace Open.Text.Tests;
66
public static class ComparableTests
77
{
88
[Theory]
9+
[InlineData(null, null)]
910
[InlineData("ABC", "abc")]
1011
[InlineData("XyZ", "xYz")]
11-
public static void CaseInsensitive(string a, string b)
12+
public static void CaseInsensitive(string? a, string? b)
1213
{
1314
var cA = a.AsCaseInsensitive();
1415
var cB = b.AsCaseInsensitive();
@@ -23,6 +24,8 @@ public static void CaseInsensitive(string a, string b)
2324
var sB = b.AsSpan().AsCaseInsensitive();
2425

2526
Assert.True(sA == sB);
27+
if (a is null || b is null) return;
28+
2629
Assert.True(sA == a);
2730
Assert.True(sB == b);
2831
Assert.True(sB == a);
@@ -76,4 +79,29 @@ public static void CaseSensitive(string a, string b)
7679
Assert.False(sB == cA);
7780
Assert.True(sB == cB);
7881
}
82+
83+
[Fact]
84+
public static void NullTests()
85+
{
86+
var cA = "ABC".AsCaseInsensitive();
87+
var cB = default(string).AsCaseInsensitive();
88+
Assert.False(cA == cB);
89+
Assert.True(cA != cB);
90+
Assert.False(cB == cA);
91+
Assert.True(cB != cA);
92+
93+
cA = "".AsCaseInsensitive();
94+
cB = default(string).AsCaseInsensitive();
95+
Assert.False(cA == cB);
96+
Assert.True(cA != cB);
97+
Assert.False(cB == cA);
98+
Assert.True(cB != cA);
99+
100+
cA = default(string).AsCaseInsensitive();
101+
cB = default(string).AsCaseInsensitive();
102+
Assert.True(cA == cB);
103+
Assert.False(cA != cB);
104+
Assert.True(cB == cA);
105+
Assert.False(cB != cA);
106+
}
79107
}

0 commit comments

Comments
 (0)