Pineapple 2.0.0
dotnet add package Pineapple --version 2.0.0
NuGet\Install-Package Pineapple -Version 2.0.0
<PackageReference Include="Pineapple" Version="2.0.0" />
<PackageVersion Include="Pineapple" Version="2.0.0" />
<PackageReference Include="Pineapple" />
paket add Pineapple --version 2.0.0
#r "nuget: Pineapple, 2.0.0"
#:package Pineapple@2.0.0
#addin nuget:?package=Pineapple&version=2.0.0
#tool nuget:?package=Pineapple&version=2.0.0
Pineapple — Guava-inspired core utilities for .NET
Compatibility APIs with platform replacements remain available through 2.x and report migration diagnostics. See the migration guide.
<img src="/_dp/https://raw.githubusercontent.com/MILL5/pineapple/main/pineapple.png" alt="Pineapple logo" width="96" align="right" />
Pineapple is an open-source C# library of core utilities for .NET 8, 9, 10, and 11 RC, inspired by Google's Guava. It gives you guard clauses (preconditions), URL-safe 22-character ShortGuids, a deterministic xxHash HashCode, a SQL Server RowVersion type, calls-per-minute rate limiting and resource governors, timeouts, exponential backoff, timing scopes, and exception-safe cleanup helpers — small, dependency-light building blocks you would otherwise rewrite in every project.
📖 Documentation: Pineapple guides · Project documentation
Install
dotnet add package Pineapple --version 2.0.0
dotnet add package Pineapple.Data --version 2.0.0 # optional: SQL Server / EF Core helpers
Pineapple and Pineapple.Data share version 2.0.0 and release together. Keep direct references to both packages on the same version.
| Package | Targets | What's inside |
|---|---|---|
Pineapple |
.NET 8, 9, 10, 11 RC | Preconditions, ShortGuid, HashCode, RowVersion, Cleanup, threading, diagnostics, health checks, Brotli handler |
Pineapple.Data |
.NET 8 (EF Core 8), .NET 9 (EF Core 9), .NET 10/11 (EF Core 10) | EF Core model for INFORMATION_SCHEMA, SQL Server availability check |
Quick start
using Pineapple.Common;
using Pineapple.Diagnostics;
using static Pineapple.Common.Preconditions;
using HashCode = Pineapple.Common.HashCode;
public sealed class OrderService(IOrderRepository repository, ILogger<OrderService> logger)
{
public async Task<Order> GetAsync(string orderId, int quantity)
{
// Guard clauses throw ArgumentException-family exceptions with useful messages.
CheckIsNotNullOrWhitespace(nameof(orderId), orderId);
CheckIsNotLessThan(nameof(quantity), quantity, 1);
// A ShortGuid is a Guid encoded as 22 URL-safe characters.
ShortGuid id = orderId;
// Same inputs and byte encoding yield the same hash across processes and restarts.
var cacheKey = HashCode.Combine("order", id.Guid.ToString(), quantity);
// Logs "Operation [LoadOrder] called from [GetAsync] took 12.34ms" at Debug level.
using (new TimingScope("LoadOrder", logger))
{
return await repository.GetAsync(id.Guid, cacheKey);
}
}
}
Features
| Area | Types | Use it to |
|---|---|---|
| Guard clauses | Preconditions |
Validate arguments: null/whitespace, ranges, dates, URIs, GUIDs, custom conditions |
| Identifiers | ShortGuid, GuidExtensions |
Shorten GUIDs for URLs; sort GUIDs the way SQL Server does |
| Hashing | HashCode |
Combine values into a hash that is stable across processes (xxHash32), unlike System.HashCode |
| Concurrency tokens | RowVersion |
Compare, order, and convert SQL Server rowversion/timestamp values |
| Parallelism | Parallelism |
Size Parallel.ForEach loops to the machine's CPUs |
| Diagnostics | TimingScope, ConsoleColorScope |
Log how long an operation took with structured ILogger events |
| Async plumbing | SynchronizationContextScope, SuppressSynchronizationContextScope |
Avoid sync-over-async deadlocks |
| Cleanup | Cleanup.SafeMethod |
Run cleanup code that must never throw |
| Schema | InformationSchemaContext |
Query SQL Server INFORMATION_SCHEMA with LINQ |
See the documentation site for a guide to each area.
Deprecated in 2.0
.NET now ships built-in replacements for these, so they are marked [Obsolete] (diagnostics PINE001–PINE008) and will be removed in 3.0. The migration guide shows each replacement.
| Deprecated | Use instead |
|---|---|
BrotliCompressionHandler |
AutomaticDecompression = DecompressionMethods.All |
ResourceGoverner, RateLimiterScope, SafeRateLimiterScope, SemaphoreRateLimiterScope |
System.Threading.RateLimiting |
AccurateTimeout, SimpleTimeout, ExponentialWait |
CancellationTokenSource, Task.WaitAsync, Polly retry |
MeasureScope, CallsPerMinute |
System.Diagnostics.Metrics |
Scavenger |
PeriodicTimer |
Health.Check, Data.SqlClient.Check |
Microsoft.Extensions.Diagnostics.HealthChecks |
ImmutableExtensions |
ImmutableList.Add / AddRange |
ServiceCollectionExtensions |
TryAddSingleton |
FAQ
What is Pineapple? An Apache-2.0-licensed set of C# utility classes for .NET from MILL5, modeled on Google's Guava library for Java, with 110K+ NuGet downloads.
Which .NET versions are supported? .NET 8, 9, 10, and 11 (release candidate). Version 1.x targeted .NET Standard 2.0; use Pineapple 1.0.41 if you still need .NET Framework.
How is Pineapple.Common.HashCode different from System.HashCode? System.HashCode is randomized per process. Pineapple's HashCode uses xxHash32, so the same inputs and byte encoding give the same hash across application instances — useful for caching keys, sharding, and persisted hashes.
What is a ShortGuid? A 128-bit Guid encoded as 22 URL-safe Base64 characters (- and _ instead of + and /, no padding) — 14 characters shorter than the standard 36-character form, with implicit conversions to and from Guid and string.
More questions: FAQ.
Building from source
Requires the .NET 11 release-candidate SDK pinned in global.json, plus .NET 8, 9, and 10 runtimes for their tests. .NET 11 coverage uses a release candidate until GA.
dotnet build Pineapple.slnx
dotnet test --solution Pineapple.slnx
dotnet pack Pineapple.slnx -c Release -o artifacts
bash scripts/verify-packages.sh artifacts # requires Python 3
Part of the MILL5 open-source family
FastSearch · M5.BloomFilter · yocto · Polygon.Net · Cut & Move · MacEdgeLight
Contributing
Issues and pull requests are welcome. See CHANGELOG.md for release history.
License
This project is licensed under the Apache License 2.0. © MILL5, LLC.
Credits
Created by Richard Crane — Microsoft MVP and founder of MILL5.
- MILL5: mill5.com
- Microsoft MVP profile: mvp.microsoft.com/…/Richard-Crane
- Podcast — Inventing Fire with AI: inventingfirewith.ai
- Support: rich@mill5.com
Powered by MILL5 Explore Richard Crane on Microsoft MVP Listen to the Inventing Fire with AI podcast for insights on technology and innovation. For support, contact: rich@mill5.com
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 is compatible. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. net11.0 is compatible. |
-
net10.0
- K4os.Hash.xxHash (>= 1.0.8)
- Microsoft.Extensions.Http (>= 10.0.14)
- Microsoft.Extensions.Logging.Abstractions (>= 10.0.14)
-
net11.0
- K4os.Hash.xxHash (>= 1.0.8)
- Microsoft.Extensions.Http (>= 10.0.14)
-
net8.0
- K4os.Hash.xxHash (>= 1.0.8)
- Microsoft.Bcl.Memory (>= 10.0.14)
- Microsoft.Extensions.Http (>= 10.0.14)
- Microsoft.Extensions.Logging.Abstractions (>= 10.0.14)
-
net9.0
- K4os.Hash.xxHash (>= 1.0.8)
- Microsoft.Extensions.Http (>= 10.0.14)
- Microsoft.Extensions.Logging.Abstractions (>= 10.0.14)
NuGet packages (11)
Showing the top 5 NuGet packages that depend on Pineapple:
| Package | Downloads |
|---|---|
|
Polygon.Net
A .NET class library for use against the Polygon APIs supporting .NET Standard, .NET Core, .NET 5.0, and the new .NET 6.0 |
|
|
Intrinio.Net
This is a port of the Intrinio.Net to .NET Standard so that it can be used across .NET Framework, .NET Core, .NET 6.0+. |
|
|
FastSearch
Fast, low-memory, case-insensitive substring (contains) search over in-memory collections of objects. NGramSearch indexes 1M items in about 1 s with 47 MiB and answers typical queries in about 5 µs. |
|
|
M5.BloomFilter
A Bloom filter for .NET 10 and .NET 11. Lock-free lookups, allocation-free string, numeric and span keys, sizing from an expected count and a false-positive target, occupancy estimates, union of compatible filters, immutable snapshots, and a versioned persisted format with JSON and protobuf companion packages. |
|
|
M5Finance
M5Finance is an aggregation of as many free and public sources of financial data. This includes NASDAQ, NYSE, and NYSE American stock exchanges. |
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 2.0.0 | 120 | 11/3/2026 |
| 1.0.41 | 29,285 | 9/5/2022 |
| 1.0.40 | 698 | 9/4/2022 |
| 1.0.36 | 25,425 | 9/3/2021 |
| 1.0.35 | 3,805 | 8/26/2021 |
| 1.0.34 | 10,685 | 7/22/2021 |
| 1.0.33 | 663 | 7/22/2021 |
| 1.0.32-alpha | 1,210 | 7/13/2021 |
| 1.0.31-alpha | 540 | 7/12/2021 |
| 1.0.30 | 6,140 | 3/30/2021 |
| 1.0.30-alpha | 529 | 7/12/2021 |
| 1.0.29-alpha | 1,157 | 3/26/2021 |
| 1.0.28-alpha | 472 | 3/26/2021 |
| 1.0.27-alpha | 503 | 3/25/2021 |
| 1.0.26-alpha | 623 | 3/21/2021 |
| 1.0.24-alpha | 547 | 3/17/2021 |
| 1.0.23-alpha | 530 | 3/17/2021 |
| 1.0.22-alpha | 546 | 3/16/2021 |
| 1.0.20-alpha | 541 | 3/12/2021 |
| 1.0.19-alpha | 608 | 3/7/2021 |
2.0.0: Targets .NET 8, 9, 10, and 11 RC; retains K4os xxHash and persisted results. Modernizes supported utilities and dependencies; legacy APIs with platform replacements remain available through 2.x with PINE001-PINE008 migration diagnostics. See https://github.com/MILL5/pineapple/blob/main/CHANGELOG.md