SG.NullableExtensions 1.0.0

dotnet add package SG.NullableExtensions --version 1.0.0                
NuGet\Install-Package SG.NullableExtensions -Version 1.0.0                
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="SG.NullableExtensions" Version="1.0.0" />                
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add SG.NullableExtensions --version 1.0.0                
#r "nuget: SG.NullableExtensions, 1.0.0"                
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
// Install SG.NullableExtensions as a Cake Addin
#addin nuget:?package=SG.NullableExtensions&version=1.0.0

// Install SG.NullableExtensions as a Cake Tool
#tool nuget:?package=SG.NullableExtensions&version=1.0.0                

Nullable Extensions

This is a set of extension methods for C# nullable types (reference types and the Nullable<T> struct) that allow you to ger rid of if statements used to check for null.

Methods

All of these methods has async overloads. You can find them in SG.NullableExtensions.Tasks and SG.NullableExtensions.ValueTasks namespaces.

Inspect

Inspect() performs an action against a value if the value is not null.

var product = products.FirstOrDefault(p => p.Code == Code);
product.Inspect(product => product.UpdatedDate = DateTime.NowUtc);

Inspect() has async overloads that support both Task<T> and ValueTask<T>:

var delivery = await delivery.GetProductAsync(id);
await product.InspectAsync(p => {
    p.Address = await addressService.GetByPostalCodeAsync(p.PostalCode)
});

In addition to that, there are extensions for ValueTask<T?> and Task<T?>, they will await the given tasks for you if needed, so the Inspect() is applied to the output of the task.

await serializer.SerializeAsync()
    .InspectAsync(message => processor.ProcessAsync(message)); // takes Task<T?>, applies Func<T, Task>

WhenNull

This method as opposed to Inspect() calls the delegate when the value is null.

await serializer.Serialize()
    .WhenNull(message => logger.LogError("Failed to serialize a message!"));

Please, note: Inspect() and WhenNull() return the unchanged value, so you can combine these methods:

await serializer.Serialize()
    .WhenNull(() => logger.LogError("Failed to serialize message!"))
    .Inspect(message => logger.LogInformation(message))
    .Inspect(message => processor.Process(message));

WhenNull() has the same set of async overloads as Inspect().

await serializer.SerializeAsync()
    .WhenNullAsync(() => logger.NotifyAsync("Failed to serialize a message!")); // takes Task<T?>, applies Func<Task>
});

await serializer.Serialize()
    .WhenNullAsync(() => notifier.NotifyAsync("Failed to serialize message!")); // takes T?, applies Func<Task>

Is

Checks if the underlying value is not null. If so, it'll run specified predicate.

var user = userService.GetUser(id);
user.Is(u => u.EmailAddress == emailAddress);

Also, async overloads available.

var user = userService.GetUser(id);
await user.IsAsync(u => userOrderService.HasPendingOrdersAsync(u.Id));

await userService.GetUserAsync(id).IsAsync(u => userOrderService.HasPendingOrdersAsync(u.Id));

Map

Transforms the underlying value if it is not null.

var user = await dbContext.User
    .FirstOrDefault(u => u.Id == id)
    .Map(u => new UserModel(u));

Supports an async overload:

var user = await httpContext.Read()
    .MapAsync(b => JsonSerializer.DeserializeAsync<User>(u));

ValueTask<T?> and Task<T?> overloads are supported as well:

var authorizationResult = await httpContext.ReadAsJsonAsync<Credentials>()
    .MapAsync(credentials => authService.AuthorizeAsync(credentials));

var userDto = await httpContext.ReadAsJsonAsync<User>()
    .MapAsync(credentials => mapper.Map<UserDto>());

ValueOr

Tries to unwrap the underlying value. If the value is null, it will return specified default value.

var address = employee.Address.ValueOr(new Address());

Also, there is an overload that uses a factory instead of a plain value.

var address = employee.Address.ValueOr(() => addressService.GetDefaultAddress());

There are also async overloads including ValueTas<T> and Task<T> extensions.

var apiKey = await apiKeysCache
    .Get()
    .ValueOrAsync(() => await apiKeysService.RefreshAsync())
    .InspectAsync(key => await apiKeysCache.SetAsync(key))
    
var apiKey = await apiKeysCache
    .GetAsync()
    .ValueOrAsync(() => await apiKeysService.RefreshAsync()) // takes Task<T?>, applies Func<Task>
    .InspectAsync(key => await apiKeysCache.SetAsync(key))
Product 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. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • net8.0

    • No dependencies.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last updated
1.0.0 76 7/24/2024
0.1.0 84 7/19/2024