Why the Change?
The Option<T> class served as a good starting point for building a functional class that manages having a value or not, but its naming doesn’t align well with .NET conventions because it already has the concept of Option for defining application settings. Therefore, we’ve introduced a new Optional<T> type that’s cleaner, more consistent, and easier to evolve. However, this change introduces a breaking change to our D20Tek.Functional package.
- Package link on NuGet.Org.
- GitHub repository.
To address this, we have rolled out these changed is part of a staged migration:
- 0.9.16 and earlier –
Option<T>was the only API. - 0.9.17 – new
Optional<T>class and helpers introduced,Option<T>still works but is marked[Obsolete]. - 1.0.1 – Breaking change:
Option<T>and related types removed entirely.
What Happened in 0.9.17
Optional<T>added as the new core type.- New factory methods on the static
Optionalclass:
var some = Optional.Some(42);
var none = Optional.None<int>();
- Added internal
SomeOptional<T>/NoneOptional<T>types back for the factories.
You don’t need to reference them directly (other than as instances of Optional<T>). - Legacy API still available but marked
[Obsolete]:Option<T>Optionstatic classSome<T>,None<T>ToOption()extensions
What Changed in 1.0.1
- Removed all
Option-based types:Option<T>Optionstatic classSome<T>,None<T>(legacy versions)ToOption()extensions
- Added public
Some<T>/None<T>types that now derive fromOptional<T>for full pattern-matching support:
switch (result)
{
case Some<int> some:
Console.WriteLine($"Value: {some.Content}");
break;
case None<int>:
Console.WriteLine("No value");
break;
}
Migration Steps
1. Replace Option<T> with Optional<T>
Before (0.9.16):
Option<string> name = Option.Some("Alice");
After (0.9.17+):
Optional<string> name = Optional.Some("Alice");
2. Update Factory Methods
Before:
var some = Option.Some(99);
var none = Option.None<int>();
After:
var some = Optional.Some(99);
var none = Optional.None<int>();
3. Replace ToOption() with ToOptional()
Before:
var maybeValue = value.ToOption();
After:
var maybeValue = value.ToOptional();
4. Pattern Matching Support
- In 0.9.17, pattern matching only worked with the old
Some<T>/None<T>types. - In 1.0.1,
Some<T>andNone<T>now derive fromOptional<T>, so you can match directly on them:
if (opt is Some<int> some)
{
Console.WriteLine(some.Content);
}
Version Timeline
| Version | What Happens |
|---|---|
| 0.9.16 | Option<T> only |
| 0.9.17 | Optional<T> added, Option<T> deprecated, no breaking changes |
| 1.0.1 | Option<T> removed, Some<T> / None<T> changed to derive from Optional<T> |
Quick Find/Replace Cheatsheet
| Old Code | New Code |
|---|---|
Option<T> | Optional<T> |
Option.Some(value) | Optional.Some(value) |
Option.None<T>() | Optional.None<T>() |
value.ToOption() | value.ToOptional() |
Some<T> / None<T> (0.9.17) | Use Optional<T> factories |
Final Notes
- If you’re on 0.9.16, upgrade to 0.9.17 first and migrate to
Optional<T>to avoid breakage. - If you upgrade straight to 1.0.1, you’ll need to replace all
Optionreferences in your code immediately. - The new
Some<T>/None<T>in 1.0.1 support full C# pattern matching.