WicalWare.ResultCs
0.1.10
dotnet add package WicalWare.ResultCs --version 0.1.10
NuGet\Install-Package WicalWare.ResultCs -Version 0.1.10
<PackageReference Include="WicalWare.ResultCs" Version="0.1.10" />
<PackageVersion Include="WicalWare.ResultCs" Version="0.1.10" />
<PackageReference Include="WicalWare.ResultCs" />
paket add WicalWare.ResultCs --version 0.1.10
#r "nuget: WicalWare.ResultCs, 0.1.10"
#:package WicalWare.ResultCs@0.1.10
#addin nuget:?package=WicalWare.ResultCs&version=0.1.10
#tool nuget:?package=WicalWare.ResultCs&version=0.1.10
Result C#
Status
Additional Information
If you'd like to explore the package more and see in-depth details about this package, please go here: https://milowical.github.io/Result-Cs/
Motivation
null is a problematic value for many developers, and in the Rust language a conscious decision to NOT include null was made to prevent a whole class of problems. As stated in The Rust Programming Language:
Programming language design is often thought of in terms of which features you include, but the features you exclude are important too. Rust doesn’t have the null feature that many other languages have. Null is a value that means there is no value there. In languages with null, variables can always be in one of two states: null or not-null.
In his 2009 presentation “Null References: The Billion Dollar Mistake,” Tony Hoare, the inventor of null, has this to say:
"I call it my billion-dollar mistake. At that time, I was designing the first comprehensive type system for references in an object-oriented language. My goal was to ensure that all use of references should be absolutely safe, with checking performed automatically by the compiler. But I couldn’t resist the temptation to put in a null reference, simply because it was so easy to implement. This has led to innumerable errors, vulnerabilities, and system crashes, which have probably caused a billion dollars of pain and damage in the last forty years."
If you'd like to hear it in his own words: Null References: The Billion Dollar Mistake
The amount of code that I've written over my career led me to appreciate the insightfulness of the Rust language developers in avoiding null, so I decided to write this package in order to give .NET developers the same opportunity for goodness. 😁 ⚡ 🤘
Overview
The Rust paradigm for avoiding null as a concept involves the use of using enumerations ("enums") that wrap values against which typechecking can be performed.
Option<T>
The simplest value implemented in this library is the Option<T> type. It consists of 2 enum values:
None: Indicates that theOptionhas no usable value (closest to the intuitive notion ofnull)Some: Indicates that theOptionhas a value of typeTthat can be "unwrapped" (Rust idiom) to get to the internal value, which will never benull.
Option Example
Below is an example of using Option<T> to introduce null-safety:
string text = "Bacon ipsum";
var nullSafeLength = text.NullSafeLength();
if (nullSafeLength.IsNone())
{
Console.WriteLine("The length for the string doesn't exist.");
}
else if (nullSafeLength.IsSome())
{
Console.WriteLine($"The length of the string is: {nullSafeLength.Unwrap()}");
}
public static class NullSafeExtensions
{
public static Option<int> NullSafeLength(this string s)
{
if (s is null)
{
return Option<int>.None();
}
return Option<int>.Some(s.Length);
}
}
Result<T, E>
The Result<T, E> type is slightly more complex than the Option<T> type, though the general thought processes are directly applicable. The Result can wrap values of one of two types:
T: The wrapped type to return in the event the resulting value has semantic value.E: An error type that allows the implementer to return a value that indicates that the operation was unsuccessful without either:- Returning
null - Throwing an exception
- Returning
The Result comes in two flavors:
Ok: Indicates that the output has validity for additional processing and can be safely unwrapped.Err: Indicates that the result of the operation was unsuccessful and carries additional details important to the caller about the failure.
Result Example
A basic application that uses the Result<T, E> type might look like this:
Console.Write("Enter a numerator: ");
var numeratorStr = Console.ReadLine();
Console.Write("Enter a denominator: ");
var denominatorStr = Console.ReadLine();
var result = ToDecimal(numeratorStr, denominatorStr);
if (result.IsErr())
{
Console.WriteLine(result.UnwrapErr());
}
else if (result.IsOk())
{
Console.WriteLine($"The resulting decimal is: {result.Unwrap()}");
}
public Result<double, string> ToDecimal(string numStr, string denStr)
{
if (!double.TryParse(numStr, out var num))
{
return Result<double, string>.Err($"The value '{numStr}' could not be parsed to a double.");
}
if (!double.TryParse(denStr, out var den))
{
return Result<double, string>.Err($"The value '{denStr}' could not be parsed to a double.");
}
if (denStr == 0)
{
return Result<double, string>.Err("Cannot divide by zero.");
}
return Result<double, string>.Ok(num / den);
}
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net6.0 is compatible. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 is compatible. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. 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 was computed. 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 was computed. 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. |
-
net6.0
- No dependencies.
-
net7.0
- No dependencies.
-
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 |
|---|---|---|
| 0.1.10 | 257 | 1/15/2024 |
| 0.1.10-rc | 134 | 1/15/2024 |
| 0.1.9 | 200 | 1/15/2024 |
| 0.1.9-rc | 152 | 1/15/2024 |
| 0.1.8 | 211 | 1/15/2024 |
| 0.1.8-rc | 145 | 1/15/2024 |
| 0.1.1 | 295 | 7/21/2023 |
| 0.1.1-rc | 232 | 7/21/2023 |
| 0.1.0 | 265 | 7/20/2023 |
| 0.1.0-rc | 227 | 7/20/2023 |
| 0.0.9 | 258 | 7/20/2023 |
| 0.0.9-rc | 237 | 7/20/2023 |
| 0.0.8 | 250 | 7/20/2023 |
| 0.0.8-rc | 228 | 7/20/2023 |
| 0.0.7 | 255 | 7/20/2023 |
| 0.0.7-rc | 226 | 7/20/2023 |
| 0.0.6 | 263 | 7/20/2023 |
| 0.0.6-rc | 229 | 7/20/2023 |
| 0.0.5 | 250 | 7/20/2023 |
| 0.0.5-rc | 218 | 7/20/2023 |