Skip to content

Commit 7aa3d05

Browse files
Refactor to use primary constructors and update targets
Refactored multiple classes to use C# 9.0 primary constructors, simplifying initialization and improving readability. Updated project files to target .NET 9.0 and included new package references. Suppressed specific style warnings and added XML documentation to various classes. Enhanced thread-safety and nullability handling in several methods. Improved test classes with modern C# features and updated array initializations.
1 parent 89807b4 commit 7aa3d05

File tree

83 files changed

+892
-626
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

83 files changed

+892
-626
lines changed

.editorconfig

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,8 @@ dotnet_diagnostic.IDE0057.severity = silent
226226
dotnet_diagnostic.CS1591.severity = suggestion
227227
csharp_style_prefer_method_group_conversion = true:silent
228228
csharp_style_prefer_top_level_statements = true:silent
229+
csharp_style_prefer_primary_constructors = true:suggestion
230+
csharp_prefer_system_threading_lock = true:suggestion
229231
#dotnet_diagnostic.SA0001.severity = suggestion
230232
[*.{cs,vb}]
231233
dotnet_style_coalesce_expression = true:warning
@@ -234,4 +236,10 @@ tab_width = 4
234236
indent_size = 4
235237
end_of_line = crlf
236238
dotnet_style_null_propagation = true:warning
237-
indent_style = tab
239+
indent_style = tab
240+
dotnet_style_prefer_is_null_check_over_reference_equality_method = true:warning
241+
dotnet_style_prefer_auto_properties = true:suggestion
242+
dotnet_style_object_initializer = true:suggestion
243+
dotnet_style_collection_initializer = true:suggestion
244+
dotnet_style_prefer_simplified_boolean_expressions = true:warning
245+
dotnet_diagnostic.CA2007.severity = error

Trie/ConcurrentTrie.cs

Lines changed: 5 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -6,22 +6,13 @@ namespace Open.Collections;
66
/// <summary>
77
/// A generic Trie collection.
88
/// </summary>
9-
public sealed class ConcurrentTrie<TKey, TValue>
10-
: TrieBase<TKey, TValue>
9+
public sealed class ConcurrentTrie<TKey, TValue>(
10+
IEqualityComparer<TKey>? equalityComparer = null)
11+
: TrieBase<TKey, TValue>(() => new Node(equalityComparer))
1112
where TKey : notnull
1213
{
13-
/// <summary>
14-
/// Constructs a <see cref="ConcurrentTrie{TKey, TValue}"/>.
15-
/// </summary>
16-
public ConcurrentTrie(IEqualityComparer<TKey>? equalityComparer = null)
17-
: base(() => new Node(equalityComparer))
18-
{ }
19-
20-
private sealed class Node : NodeBase
14+
private sealed class Node(IEqualityComparer<TKey>? equalityComparer) : NodeBase
2115
{
22-
public Node(IEqualityComparer<TKey>? equalityComparer)
23-
=> _equalityComparer = equalityComparer;
24-
2516
private readonly object _valueSync = new();
2617

2718
protected override void SetValue(TValue value)
@@ -31,7 +22,7 @@ protected override void SetValue(TValue value)
3122

3223
private readonly object _childSync = new();
3324

34-
private readonly IEqualityComparer<TKey>? _equalityComparer;
25+
private readonly IEqualityComparer<TKey>? _equalityComparer = equalityComparer;
3526
private ConcurrentDictionary<TKey, ITrieNode<TKey, TValue>>? _children;
3627

3728
protected override void UpdateRecent(TKey key, ITrieNode<TKey, TValue> child)

Trie/Open.Collections.Trie.csproj

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
2727
<PackageIcon>logo.png</PackageIcon>
2828
<PackageReadmeFile>README.md</PackageReadmeFile>
29+
<NoWarn>IDE0130;</NoWarn>
2930
</PropertyGroup>
3031

3132
<ItemGroup>
@@ -44,11 +45,11 @@
4445
</ItemGroup>
4546

4647
<ItemGroup>
47-
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.1.1" PrivateAssets="All" />
48+
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="8.0.0" PrivateAssets="All" />
4849
</ItemGroup>
4950

5051
<ItemGroup Condition=" '$(TargetFramework)' == 'netstandard2.0' ">
51-
<PackageReference Include="System.Memory" Version="4.5.1" />
52+
<PackageReference Include="System.Memory" Version="4.6.0" />
5253
</ItemGroup>
5354

5455
</Project>

Trie/StringJoinPool.cs

Lines changed: 5 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -12,22 +12,12 @@ namespace Open.Collections;
1212
/// <remarks>
1313
/// Useful for (re)generating cache keys.
1414
/// </remarks>
15-
public class StringJoinPool
15+
public class StringJoinPool(
16+
ITrie<string, string> pool, ReadOnlyMemory<char> separator)
1617
{
17-
private readonly ReadOnlyMemory<char> _separator;
18-
private readonly ITrie<string, string> _pool;
18+
private readonly ITrie<string, string> _pool = pool ?? throw new ArgumentNullException(nameof(pool));
1919
private StringBuilder? _reusableBuilder;
2020

21-
/// <summary>
22-
/// Constructs a <see cref="StringJoinPool"/>.
23-
/// </summary>
24-
/// <exception cref="ArgumentNullException">If the supplied pool is null.</exception>
25-
public StringJoinPool(ITrie<string, string> pool, ReadOnlyMemory<char> separator)
26-
{
27-
_pool = pool ?? throw new ArgumentNullException(nameof(pool));
28-
_separator = separator;
29-
}
30-
3121
/// <inheritdoc cref="StringJoinPool(ITrie{string, string}, ReadOnlyMemory{char})"/>
3222
public StringJoinPool(ITrie<string, string> pool, string? separator = null)
3323
: this(pool, separator is null ? ReadOnlyMemory<char>.Empty : separator.AsMemory())
@@ -75,7 +65,7 @@ string Build(ReadOnlySpan<string> segments)
7565
int len = segments.Length;
7666
try
7767
{
78-
if (_separator.IsEmpty)
68+
if (separator.IsEmpty)
7969
{
8070
for (int i = 0; i < len; i++)
8171
AppendSegment(sb, segments[i]);
@@ -85,7 +75,7 @@ string Build(ReadOnlySpan<string> segments)
8575
Debug.Assert(segments.Length != 0);
8676

8777
AppendSegment(sb, segments[0]);
88-
var sepSpan = _separator.Span;
78+
var sepSpan = separator.Span;
8979
int sLen = sepSpan.Length;
9080

9181
for (int i = 1; i < len; i++)
Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,21 @@
11
#if NETSTANDARD2_0
2+
23
namespace System.Diagnostics.CodeAnalysis;
34

45
// Use a shim for simplicity.
56

67
/// <summary>
78
/// Indicates that the output may be null even if the corresponding type disallows it.
89
/// </summary>
10+
/// <remarks>
11+
/// Constructs a <see cref="MaybeNullWhenAttribute"/>.
12+
/// </remarks>
913
[AttributeUsage(AttributeTargets.Parameter, Inherited = false)]
10-
internal sealed class MaybeNullWhenAttribute : Attribute
14+
internal sealed class MaybeNullWhenAttribute(bool returnValue) : Attribute
1115
{
12-
/// <summary>
13-
/// Constructs a <see cref="MaybeNullWhenAttribute"/>.
14-
/// </summary>
15-
public MaybeNullWhenAttribute(bool returnValue)
16-
=> ReturnValue = returnValue;
17-
1816
/// <summary>
1917
/// The return value condition.
2018
/// </summary>
21-
public bool ReturnValue { get; }
19+
public bool ReturnValue { get; } = returnValue;
2220
}
2321
#endif

Trie/Trie.cs

Lines changed: 7 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -4,34 +4,25 @@ namespace Open.Collections;
44
/// <summary>
55
/// A generic Trie collection.
66
/// </summary>
7-
public sealed class Trie<TKey, TValue>
8-
: TrieBase<TKey, TValue>
7+
public sealed class Trie<TKey, TValue>(
8+
IEqualityComparer<TKey>? equalityComparer = null)
9+
: TrieBase<TKey, TValue>(() => new Node(equalityComparer))
910
where TKey : notnull
1011
{
11-
/// <summary>
12-
/// Constructs a <see cref="Trie{TKey, TValue}"/>.
13-
/// </summary>
14-
public Trie(IEqualityComparer<TKey>? equalityComparer = null)
15-
: base(() => new Node(equalityComparer))
16-
{ }
17-
18-
private sealed class Node : NodeBase
12+
private sealed class Node(IEqualityComparer<TKey>? equalityComparer)
13+
: NodeBase
1914
{
20-
private readonly IEqualityComparer<TKey>? _equalityComparer;
2115
private Dictionary<TKey, ITrieNode<TKey, TValue>>? _children;
2216

23-
public Node(IEqualityComparer<TKey>? equalityComparer)
24-
=> _equalityComparer = equalityComparer;
25-
2617
public override ITrieNode<TKey, TValue> GetOrAddChild(TKey key)
2718
{
2819
var children = _children;
2920
if (children is null)
30-
Children = _children = children = _equalityComparer is null ? new() : new(_equalityComparer);
21+
Children = _children = children = equalityComparer is null ? new() : new(equalityComparer);
3122
else if (TryGetChildFrom(children, key, out var c))
3223
return c;
3324

34-
var child = new Node(_equalityComparer);
25+
var child = new Node(equalityComparer);
3526
children[key] = child;
3627
return child;
3728
}

Trie/TrieBase.cs

Lines changed: 8 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -221,34 +221,23 @@ internal abstract class NodeBase : ITrieNode<TKey, TValue>
221221
{
222222
protected IDictionary<TKey, ITrieNode<TKey, TValue>>? Children;
223223

224-
private readonly struct ValueContainer
224+
private readonly struct ValueContainer(bool isSet, TValue value)
225225
{
226-
public ValueContainer(bool isSet, TValue value)
227-
{
228-
IsSet = isSet;
229-
Value = value;
230-
}
231-
232226
public ValueContainer(TValue value)
233227
: this(true, value) { }
234228

235-
public bool IsSet { get; }
236-
public TValue Value { get; }
229+
public bool IsSet { get; } = isSet;
230+
public TValue Value { get; } = value;
237231
}
238232

239233
private ValueContainer _value;
240234

241-
private readonly struct Recent
235+
private readonly struct Recent(
236+
bool exists, TKey key, ITrieNode<TKey, TValue> child)
242237
{
243-
public Recent(bool exists, TKey key, ITrieNode<TKey, TValue> child)
244-
{
245-
Exists = exists;
246-
Key = key;
247-
Child = child;
248-
}
249-
public bool Exists { get; }
250-
public TKey Key { get; }
251-
public ITrieNode<TKey, TValue> Child { get; }
238+
public bool Exists { get; } = exists;
239+
public TKey Key { get; } = key;
240+
public ITrieNode<TKey, TValue> Child { get; } = child;
252241
}
253242

254243
// It's not uncommon to have a 'hot path' that will be requested frequently.

benchmarking/Benchmarks/CollectionBenchmark.cs

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -72,13 +72,9 @@ protected override IEnumerable<TimedResult> TestOnceInternal()
7272
}
7373
}
7474

75-
public class CollectionBenchmark : CollectionBenchmark<object>
75+
public class CollectionBenchmark(
76+
uint size, uint repeat, Func<ICollection<object>> factory) : CollectionBenchmark<object>(size, repeat, factory, _ => new object())
7677
{
77-
public CollectionBenchmark(uint size, uint repeat, Func<ICollection<object>> factory)
78-
: base(size, repeat, factory, _ => new object())
79-
{
80-
}
81-
8278
public static TimedResult[] Results<T>(uint size, uint repeat, Func<ICollection<T>> factory, Func<int, T> itemFactory)
8379
=> new CollectionBenchmark<T>(size, repeat, factory, itemFactory).Result;
8480

benchmarking/Benchmarks/CollectionParallelBenchmark.cs

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,10 @@
66

77
namespace Open.Collections;
88

9-
public class CollectionParallelBenchmark<T> : CollectionBenchmark<T>
9+
public class CollectionParallelBenchmark<T>(
10+
uint size, uint repeat, Func<ICollection<T>> factory, Func<int, T> itemFactory)
11+
: CollectionBenchmark<T>(size, repeat, factory, itemFactory)
1012
{
11-
public CollectionParallelBenchmark(uint size, uint repeat, Func<ICollection<T>> factory, Func<int, T> itemFactory) : base(size, repeat, factory, itemFactory)
12-
{
13-
}
14-
1513
protected override IEnumerable<TimedResult> TestOnceInternal()
1614
{
1715
ICollection<T> c = Param();
@@ -115,13 +113,10 @@ protected override IEnumerable<TimedResult> TestOnceInternal()
115113
}
116114
}
117115

118-
public class CollectionParallelBenchmark : CollectionParallelBenchmark<object>
116+
public class CollectionParallelBenchmark(
117+
uint size, uint repeat, Func<ICollection<object>> factory)
118+
: CollectionParallelBenchmark<object>(size, repeat, factory, _ => new object())
119119
{
120-
public CollectionParallelBenchmark(uint size, uint repeat, Func<ICollection<object>> factory)
121-
: base(size, repeat, factory, _ => new object())
122-
{
123-
}
124-
125120
public static TimedResult[] Results<T>(uint size, uint repeat, Func<ICollection<T>> factory, Func<int, T> itemFactory)
126121
=> new CollectionParallelBenchmark<T>(size, repeat, factory, itemFactory).Result;
127122

benchmarking/Benchmarks/DictionaryParallelBenchmark.cs

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,10 @@
77

88
namespace Open.Collections;
99

10-
public class DictionaryParallelBenchmark : CollectionParallelBenchmark<KeyValuePair<int, object>>
10+
public class DictionaryParallelBenchmark(
11+
uint size, uint repeat, Func<IDictionary<int, object>> factory)
12+
: CollectionParallelBenchmark<KeyValuePair<int, object>>(size, repeat, factory, i => new KeyValuePair<int, object>(i, new object()))
1113
{
12-
public DictionaryParallelBenchmark(uint size, uint repeat, Func<IDictionary<int, object>> factory)
13-
: base(size, repeat, factory, i => new KeyValuePair<int, object>(i, new object()))
14-
{
15-
}
16-
1714
protected override IEnumerable<TimedResult> TestOnceInternal()
1815
{
1916
//foreach (TimedResult t in base.TestOnceInternal())

0 commit comments

Comments
 (0)