-
Notifications
You must be signed in to change notification settings - Fork 0
D2/D-readme: rewrite the stub README into a real one (closes #118, #102) #131
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
3 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,10 +1,122 @@ | ||
| # Wolfgang.Extensions.IComparable | ||
|
|
||
| A collection of extension methods for the `IComparable` interface in C#. | ||
| Extension methods for `IComparable<T>` that make ordering and range checks read the way you'd say them — `value.IsBetween(low, high)` instead of `value.CompareTo(low) > 0 && value.CompareTo(high) < 0`. | ||
|
|
||
| ## Methods | ||
| [](https://www.nuget.org/packages/Wolfgang.Extensions.IComparable) | ||
| [](https://www.nuget.org/packages/Wolfgang.Extensions.IComparable) | ||
| [](https://github.com/Chris-Wolfgang/IComparable-Extensions/actions/workflows/pr.yaml) | ||
| [](https://github.com/Chris-Wolfgang/IComparable-Extensions/actions/workflows/release.yaml) | ||
| [](LICENSE) | ||
| [](https://dotnet.microsoft.com/) | ||
| [](https://github.com/Chris-Wolfgang/IComparable-Extensions) | ||
|
|
||
| - `IsBetween<T>(this T value, T lowerBound, T upperBound)` - Returns true when `value` is strictly greater than `lowerBound` and strictly less than `upperBound`. | ||
| - `IsInRange<T>(this T value, T lowerBound, T upperBound)` - Returns true when `value` is greater than or equal to `lowerBound` and less than or equal to `upperBound`. | ||
| --- | ||
|
|
||
| ## 📦 Installation | ||
|
|
||
| ```bash | ||
| dotnet add package Wolfgang.Extensions.IComparable | ||
| ``` | ||
|
|
||
| **NuGet Package:** [Wolfgang.Extensions.IComparable](https://www.nuget.org/packages/Wolfgang.Extensions.IComparable) | ||
|
|
||
| --- | ||
|
|
||
| ## 📄 License | ||
|
|
||
| This project is licensed under the **MIT License**. See the [LICENSE](LICENSE) file for details. | ||
|
|
||
| --- | ||
|
|
||
| ## 📚 Documentation | ||
|
|
||
| - **GitHub Repository:** [https://github.com/Chris-Wolfgang/IComparable-Extensions](https://github.com/Chris-Wolfgang/IComparable-Extensions) | ||
| - **API Documentation:** https://Chris-Wolfgang.github.io/IComparable-Extensions/ | ||
| - **CHANGELOG:** [CHANGELOG.md](CHANGELOG.md) | ||
| - **Contributing Guide:** [CONTRIBUTING.md](CONTRIBUTING.md) | ||
| - **Development Setup:** [docs/setup.md](docs/setup.md) | ||
|
|
||
| --- | ||
|
|
||
| ## ✨ Methods | ||
|
|
||
| All methods are generic extension methods on `T where T : IComparable<T>`. Both throw `ArgumentNullException` when `value` is `null`. | ||
|
|
||
| | Method | Bound semantics | Returns `true` when | | ||
| |---|---|---| | ||
| | `value.IsBetween(lowerBound, upperBound)` | **Exclusive** on both ends | `lowerBound < value < upperBound` | | ||
| | `value.IsInRange(lowerBound, upperBound)` | **Inclusive** on both ends | `lowerBound ≤ value ≤ upperBound` | | ||
|
|
||
| The distinction matters when `value` exactly equals one of the bounds: `IsBetween` returns `false`, `IsInRange` returns `true`. Pick the one whose contract you want. | ||
|
|
||
| --- | ||
|
|
||
| ## 🚀 Usage | ||
|
|
||
| ### `IsBetween` — strict bounds | ||
|
|
||
| ```csharp | ||
| using Wolfgang.Extensions.IComparable; | ||
|
|
||
| int score = 75; | ||
| bool inOpenRange = score.IsBetween(70, 80); // true — 70 < 75 < 80 | ||
| bool atLower = 70.IsBetween(70, 80); // false — 70 is NOT > 70 | ||
| bool atUpper = 80.IsBetween(70, 80); // false — 80 is NOT < 80 | ||
| ``` | ||
|
|
||
| ### `IsInRange` — inclusive bounds | ||
|
|
||
| ```csharp | ||
| using Wolfgang.Extensions.IComparable; | ||
|
|
||
| DateTime today = DateTime.UtcNow.Date; | ||
| DateTime quarterStart = new DateTime(2026, 4, 1); | ||
| DateTime quarterEnd = new DateTime(2026, 6, 30); | ||
|
|
||
| bool inQ2 = today.IsInRange(quarterStart, quarterEnd); // true on any Q2 date, | ||
| // including the boundary days | ||
| ``` | ||
|
|
||
| ### Works with any `IComparable<T>` | ||
|
|
||
| ```csharp | ||
| using Wolfgang.Extensions.IComparable; | ||
|
|
||
| // string | ||
| "banana".IsInRange("apple", "cherry"); // true — lexicographic ordering | ||
|
|
||
| // custom type — just implement IComparable<T> | ||
| public record Money(decimal Amount, string Currency) : IComparable<Money> | ||
| { | ||
| public int CompareTo(Money? other) => | ||
| // Per the IComparable<T> contract, any non-null value is | ||
| // greater than null. Returning Amount.CompareTo(other?.Amount ?? 0m) | ||
| // would be wrong for negative Amount — a negative Money would | ||
| // compare as "less than" null instead of greater. | ||
| other is null ? 1 : Amount.CompareTo(other.Amount); | ||
| } | ||
|
|
||
| var price = new Money(19.99m, "USD"); | ||
| price.IsBetween(new Money(10m, "USD"), new Money(50m, "USD")); // true | ||
| ``` | ||
|
|
||
| ### Null safety | ||
|
|
||
| ```csharp | ||
| string? maybeNull = null; | ||
| // The `!` keeps the example warning-free under <Nullable>enable</Nullable>; | ||
| // IsBetween's T is non-null, so without it the compiler complains. The | ||
| // runtime behaviour we're demonstrating is still the same: | ||
| maybeNull!.IsBetween("a", "z"); // throws ArgumentNullException("value") | ||
| ``` | ||
|
|
||
| --- | ||
|
|
||
| ## 🎯 Target frameworks | ||
|
|
||
| Multi-targeted to keep both modern .NET projects and long-tail .NET Framework consumers covered: | ||
|
|
||
| - `net462` | ||
| - `netstandard2.0` | ||
| - `net8.0` | ||
| - `net10.0` | ||
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.