I am delighted to announce the release of Spargine 10 (v2026.10.7.1) on July 1st, 2026. Spargine, my open-source project, now offers NuGet packages for .NET 10. These enhancements have been integrated across all my projects. I encourage you to explore these updates and share any feedback or suggestions for further improvements.
This version supports .NET 10, introduces new types, methods, benchmarks, and comprehensive unit tests, all aimed at improving Spargine’s performance and reliability! Notably, this release includes speed enhancements informed by benchmark tests outlined in the 5th edition of Rock Your Code: Code & App Performance for Microsoft .NET, available on Amazon.
GitHub: https://github.com/RealDotNetDave/dotNetTips.Spargine.10/releases
NuGet: http://bit.ly/dotNetDaveNuGet
You can access all the performance data for these assemblies on GitHub. I continually seek assistance with these projects. If you are interested in contributing, please don’t hesitate to contact me via email at dotnetdave@live.com. Your support and collaboration are highly appreciated!
Libraries are Now Trimmable
For this release, I invested time into making Spargine trimmable across nearly all assemblies. The only exception is the benchmarking and tester assembly, which is intentionally excluded due to its purpose and runtime behavior.
This improvement helps applications built with Spargine produce smaller deployment payloads and improve startup performance, especially in scenarios that benefit from trimming and Native AOT readiness. In short, less unused code gets carried along for the ride, and your applications can start leaner and cleaner.
If you want to see exactly how I made Spargine trimmable, check out my article, “Make Your .NET Assemblies Trimmable: Smaller Apps, Faster Starts, and AOT-Ready Code.” It breaks down the process, the challenges, and the lessons learned from making real-world .NET assemblies more trim-friendly.
New Classes and Methods
Below are the new classes and methods added to this version of Spargine.
dotNetTips.Spargine
| Type | Method | Description |
| HttpClientHelper | CreateOptimizedHttpClient() | Creates a new, performance-optimized HttpClient instance configured with the specified settings. |
dotNetTips.Spargine.Core
| Type | Method | Description |
| JsonSerialization | LoadCollectionFromJson<T>(FileInfo file, int count, JsonTypeInfo<T> typeInfo) | Reads JSON content from a specified file and deserializes it into an array of objects using a source-generated JsonTypeInfo. |
| JsonSerialization | SerializeToFile<T>(T obj, FileInfo file, JsonTypeInfo<T> typeInfo) | Serializes an object into its JSON string representation and saves it to a specified file using a source-generated JsonTypeInfo. |
| TypeHelper | FromJson<T>(string json, JsonTypeInfo<T> typeInfo) | Deserializes a JSON string into an instance of type T using the provided JsonTypeInfo. |
dotNetTips.Spargine.Extentions
| Type | Method | Description |
|---|---|---|
| EnumExtentions | GetDescription() | Gets the description of the enum value using enum metadata. |
| EnumExtentions | GetItems() | Gets the names and values of the enum. |
| HttpClientExtensions | DeleteAndDeserializeAsync() | Sends a DELETE request to the specified URL and deserializes the JSON response into an instance of TResponse. Uses stream-based deserialization to minimize memory allocations. |
| HttpClientExtentions | DownloadToStreamAsync() | Sends a GET request to the specified URL and copies the response content directly to the provided destination Stream. |
| HttpClientExtentions | GetAndDeserializeFromStreamAsync() | Sends a GET request to the specified URL and deserializes the JSON response from a stream into an instance of T. |
| HttpClientExtentions | GetStreamAsync() | Asynchronously retrieves a stream from the specified URL. |
| HttpClientExtentions | HeadersAysnc() | Sends a HEAD request to the specified URL and returns the response headers. |
| HttpClientExtentions | PatchAndDeserializeAsync() | Sends a PATCH request with a JSON-serialized body to the specified URL and deserializes the JSON response into an instance of TResponse. |
| HttpClientExtentions | PostAndDeserializeAsync() | Sends a POST request with a JSON-serialized body to the specified URL and deserializes the JSON response into an instance of TResponse using source-generated JsonTypeInfo. |
| HttpClientExtentions | PostAndEnsureSuccessAsync() | Sends a POST request with a JSON-serialized body to the specified URL and ensures a successful response, returning the HttpStatusCode |
| HttpClientExtentions | PutAndDeserializeAsync() | Sends a PUT request with a JSON-serialized body to the specified URL and deserializes the JSON response into an instance of TResponse. |
| HttpContextExtentions | GetBearerToken() | Extracts the Bearer token from the Authorization header of the current request. |
| HttpContextExtentions | GetRequestHeaderValue() | Retrieves the value of a specific request header by name. Returns null if the header is not present. |
| HttpContextExtentions | GetUserClaim() | Gets the value of a specific Claim from the authenticated user’s claims. |
| HttpContextExtentions | IsAuthenticated() | Determines whether the current user is authenticated. |
| HttpRequestExtensions | GetAbsoluteUri() | Builds the absolute Uri from the request’s scheme, host, path base, path, and query string. |
| HttpRequestExtensions | GetBearerToken() | Extracts the Bearer token from the Authorization header of the request. |
| HttpRequestExtensions | GetHeaderValue() | Retrieves the value of a specific request header by name. |
| HttpRequestExtensions | HasJsonContentType() | Determines whether the request has a JSON content type (application/json). |
| HttpRequestExtensions | IsContentType() | Determines whether the request content type matches the specified value using an ordinal case-insensitive comparison. |
| HttpRequestExtensions | TryGetBody() | Tries to deserialize the HttpRequest body into an instance of T using a source-generated JsonTypeInfo. |
| HttpResponseHeaderExtensions | AddRequestId() | Adds a unique request identifier to the HTTP response headers. |
| HttpResponseHeaderExtensions | GetETagValue() | Gets the ETag value from the response headers as a string. |
| HttpResponseHeaderExtensions | GetHeaderValue() | Gets the first value of a named header from the response headers. |
| HttpResponseHeaderExtensions | HasHeader() | Determines whether the response headers contain a header with the specified name. |
| HttpResponseHeaderExtensions | TryGetRetryAfterDelay() | Attempts to compute the retry delay from the Retry-After response header. |
| ObjectExtentions | ComputeSha256Hash() | Generates a SHA-256 hash of the object’s serialized JSON using a source-generated JsonTypeInfo. |
| SocketExtentions | ConfigureBufferSizes() | Configures the send and receive buffer sizes for the specified Socket. |
| SocketExtentions | ConfigureKeepAlive() | Configures TCP keep-alive on the specified Socket. |
| SocketExtentions | ConfigureLinger() | Configures the linger state for the specified Socket. |
| SocketExtentions | ConnectTcpAsync() | Connect TCP as an asynchronous operation. |
| SocketExtentions | TryConnectAsync() | Asynchronously attempts to connect within the provided timeout interval. |
dotNetTips.Spargine.Benchmarking
| Type | Method | Description |
|---|---|---|
| Benchmark | ConsumeEnumerable() | Consumes each item in the specified IEnumerable{T} sequence using the Consume{T} method. |
| Benchmark | ConsumeReadOnlySpan() | Consumes each item in the specified ReadOnlySpan{T} using the Consume{T} method. |
| Benchmark | MeasureAction() | Measures the elapsed time of the specified action and logs the result. |
| BenchmarkHelper | RunBenchmarks() | Runs the specified benchmark types using the provided BenchmarkDotNet configuration. Optionally saves a human-readable timing summary report to the BenchmarkDotNet artifacts directory. |
Performance Enhancements: Significant Speed Improvements Across Methods
With every new release of Spargine, I continue to focus on refining performance, reducing allocations, and improving the overall efficiency of the library. The .NET 10 version delivers substantial speed gains across many methods, with several benchmarks showing significant improvements.
Some of these gains came from careful tuning, repeated benchmarking, and focused code reviews. I also tested performance recommendations from Copilot, although the results were mixed. At the moment, roughly 50% of the performance changes suggested by Copilot actually make the code slower, which is a good reminder that every optimization must be validated with real benchmarks.
The results below highlight some of the most notable performance gains in this release, specifically methods that improved by more than 2x. In several cases, allocations also dropped dramatically, and some methods reduced allocations by 100%. That is a major win for performance-sensitive applications.
Here are the most notable speed increases:
- ArrayExtensions.AsReadOnlySpan(): 7,064x faster with no allocations.
- AssemblyExtensions.GetInstances(): 6.20x faster.
- CharacterExtensions.IsAsciiPunctuation: 2.15x faster.
- ConcurrentHashSet.Count(): 79.08x faster.
- ConcurrentHashSet.IsEmpty(): 66.31x faster.
- ConcurrentHashSet.CopyTo(): 4.06x faster.
- Enumeration.GetAll(): 26.15x faster and 4.33x less allocated.
- EnumerableExtensions.Upsert(): 5.06x faster.
- StringBuilderExtensions.BytesToString(): 3.7x faster and 2.72x less allocated.
- HashSetExtensions.Upsert(): 2.08x faster.
- ImmutableArrayExtensions.FastShuffle(): 18.84x faster and 3x less allocated.
- InMemoryCache.GetCacheItemAsync(): 14x faster.
- InMemoryCache.AddCacheItemAsync(): 3x faster.
- NumericExtensions.FormatTime(): 15.25x faster.
- ObservableCollectionExtensions.IsNotEmpty() with count: 3,897x faster and allocation eliminated.
- ObservableCollectionExtensions.IsNotEmpty() with predicate: 951.22x faster.
- ReadOnlySpanExtensions.BytesToString(): 3.48x faster.
- SortedDictionaryExtensions.IsNotEmpty() with count: 2.34x faster.
- TypeExtensions.GetAllDeclaredMethods(): 23x faster and 3.63x less allocated.
- TypeExtensions.GetAllFields(): 13x faster and 2.73x less allocated.
- TypeExtensions.GetAllMethods(): 30.22x faster and 2.73x less allocated.
- TypeExtensions.GetAllProperties(): 13x faster and 2.82x less allocated.
- TypeHelper.BuiltInTypes: 275.4x faster.
- TypeHelper.DoesObjectEqualInstance(): 105x faster.
- TypeHelper.GetAllMethods(): 74.23x faster.
- TypeHelper.GetAllDeclaredMethods(): 35.32x faster.
- TypeHelper.GetMembersWithAttribute(): 20.29x faster.
- TypeHelper.GetAllProperties(): 13.46x faster.
- TypeHelper.GetInstanceHashCode(): 11.64x faster.
- TypeHelper.GetPropertyValues(): 10.64x faster.
- TypeHelper.GetAllConstructors(): 8.37x faster.
- TypeHelper.IsEnumerable: 4.6x faster.
- TypeHelper.BuiltInTypeNames(): 3.44x faster.
- TypeHelper.GetAllDeclaredFields(): 3x faster.
Summary
I’m confident these new and enhanced Spargine features will significantly improve your projects by boosting both performance and reliability. Detailed benchmark results are available on GitHub for those who want to dig deeper.
As always, open-source thrives on community involvement. If you find these updates helpful — or have ideas for future improvements — I encourage you to jump in. Whether through pull requests, issue reports, or feature suggestions, your contributions are invaluable.
Together, we can continue to make Spargine a robust and indispensable tool for the .NET community. Your feedback is always welcome, so please share your thoughts in the comments.
If my work has helped you write faster, cleaner, rock-solid .NET code, I’d love your support through GitHub Sponsors. Your sponsorship helps fuel new features, benchmarks, tools, and learning resources for the entire community. Join the crew here: https://github.com/sponsors/RealDotNetDave — and thanks for helping keep the code loud and fast!
Thank you for your support — and keep coding faster, smarter, and better!
Do you have suggestions for Spargine?
If I use your suggestion, and you live in the US or a country I am traveling to, to speak at a conference, I will send you some cool geeky swag!
Pick up any books by David McCarter by going to Amazon.com: http://bit.ly/RockYourCodeBooks
Make a one-time donation
Make a monthly donation
Make a yearly donation
Choose an amount
Or enter a custom amount
Your contribution is appreciated.
Your contribution is appreciated.
Your contribution is appreciated.
If you liked this article, please buy David a cup of Coffee by going here: https://www.buymeacoffee.com/dotnetdave
© The information in this article is copywritten and cannot be reproduced in any way without express permission from David McCarter.
Discover more from dotNetTips.com
Subscribe to get the latest posts sent to your email.
