Corvus.Extensions
Useful C# extension methods and utilities. Sponsored by endjin.
Install / Use
/learn @corvus-dotnet/Corvus.ExtensionsREADME
Corvus.Extensions
<!-- Introduction -->This provides a library of useful extensions to .NET types.
It is built for netstandard2.0.
Repository Structure
.github- Contains GitHub repo related files, such as issue templates and GitHub Actions workflow definitionsSolutions- Contains files for all of the extension methods and tests
Getting Started
Corvus.Extensions is available on NuGet. To add a reference to the package in your project, run the following command
dotnet add package Corvus.Extensions
Use the --version option to specify a version to install.
dotnet add package Corvus.Extensions --version 1.1.4
Features
Casting
The CastTo method used to be necessary to avoid boxing in certain generic conversion cases.
The .NET framework can now determine when boxing is not necessary, so CastTo is no longer necessary, hence why we're not including an example for it.
Collection Extensions
An AddRange() extension for ICollection<T>

Dictionary Extensions
AddIfNotExists()
Adds a value to a key, if the key does not already exist.

ReplaceIfExists()
Replaces a value in a key, but only if the key already exists.

Merge()
The union of two dictionaries. Note that this uses AddIfNotExists() semantics, so the values in the first dictionary will be preserved.

Enumerable Extensions
DistinctPreserveOrder()
This emits an enumerable of the distinct items in the target, preserving their original ordering.
The built-in LINQ operator Distinct can be used to return the distinct elements from a sequence. However, the documentation makes no guarantee about preserving the original ordering of the elements.

DistinctBy()
This allows you to provide a function to provide the value for equality comparison for each item.

Concatenate()
This gives you the ability to concatenate multiple enumerables, using the params pattern.

HasMinimumCount()
This determines whether the enumerable has at least a given number of items in it.

AllAndAtLeastOne()
This is an efficient implementation of the combination of the built-in LINQ operators Any() & All() that avoids starting the enumeration twice. It determines if the collection is non-empty, and that every element also matches some predicate.
This method is also useful because of the counterintuitive behavior of All() with empty collections, whereby items.All() returns true if items is an empty collection. items.AllAndAtLeastOne() returns false if items is an empty collection, as one of the examples below shows.

Lambda Expression Extensions
ExtractPropertyName()
This extracts a property name from a lambda expression, throwing if that expression is not a MemberExpression

GetMemberExpression()
This extracts a MemberExpression from a LambdaExpression, throwing if the body is not a MemberExpression.
This allows a more direct expression of the expectation that an expression has this particular form. It allows us to avoid cluttering up the code with exception throwing, which can improve readability.

List Extensions
RemoveAll()
This removes all items from a list that match a predicate.

String Extensions
- Get as a stream in various encodings
- Base64 encode/decode (with or without URL safety)
- Reverse
- To camel case
AsBase64()
Convert the provided string to a base 64 representation of its byte representation in a particular encoding.

Base64UrlEncode()
Convert the provided string to a base 64 representation of its byte representation in the UTF8 encoding, with a URL-safe representation.

Base64UrlDecode()
Convert the provided string from a base 64 representation of its byte representation in the UTF8 encoding with a URL-safe representation.

AsStream()
Provide a stream over the string in the specified encoding.

EscapeContentType()
Escape a content type string.

FromBase64()
Decode a string from a base64-encoded byte array with the specified text encoding.

GetGraphemeClusters()
Enumerate the grapheme clusters in a string.
This method is a wrapper around StringInfo.GetTextElementEnumerator, which returns an enumerator that iterates through the text elements of a string. GetGraphemeClusters() returns an IEnumerable<string>, meaning the functionality can be used with LINQ.
You can think of GetGraphemeClusters() as enumerating through the "logical characters" in a string.

Reverse()
Reverse the string.

UnescapeContentType()
Unescape a content type string.

ToCamelCase()
Convert a string to camel case from pascal case.

Task Extensions
- Casts
Task/Task<?>toTask<T>result type with or without a cast of the actual result value
CastWithConversion()

Traversal Extensions
Various ForEach extensions, including:
- async methods
- aggregating and delaying exceptions until the end of the traversal
- with indexing
- until predicates are true/false
ForEachAsync()
Execute an async action for each item in the enumerable.

ForEachAtIndex()
Execute an action for each item in the enumerable with the index of the item in the enumerable.

ForEachAtIndexAsync()
Execute an async action for each item in the enumerable, in turn, with the index of the item in the enumerable.

ForEachFailEnd()
Execute an action for each item in the enumerable.
If any operation fails, then the enumeration is continued to the end when an Aggregate Exception is thrown containing the exceptions thrown by any failed operations.
This is useful when cleaning up Azure resources that were set up for testing purposes, for example. It makes sure that even if one step fails, the process doesn't stop, as this would mean
