Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions samples/AStar.Dev.ConsoleSample/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@
Option.Some("Jason");
Option.None<string>();
var (isSome, value) = Option.Some("hello");
Console.WriteLine(isSome);
Console.WriteLine(value);

return;

Expand Down
2 changes: 1 addition & 1 deletion samples/AStar.Dev.SampleApi/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,4 @@
ex => Results.BadRequest(new { Error = ex.Message }));
});

app.Run();
await app.RunAsync();
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ private async Task CheckUsernameAsync()
Timestamp = DateTime.Now
};

var validated = await UserService.TryValidateAsync(userInput);
var validated = await UsernameService.TryValidateAsync(userInput);

pipelineSteps.Validated = validated;
var mapped = validated.Map(name => name.ToUpper());
Expand Down Expand Up @@ -54,7 +54,7 @@ private void ToggleDebug()
debugVisible = !debugVisible;
}

private class PipelineLog
private sealed class PipelineLog
{
public string Input { get; set; } = "";
public Option<string>? Validated { get; set; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,14 @@ namespace AStar.Dev.SampleBlazor.Components.Pages;

public class UsernameService
{
public Task<Option<string>> TryValidateAsync(string input)
protected UsernameService()
{
if (string.IsNullOrWhiteSpace(input))
return Task.FromResult(Option.None<string>());
}

return Task.FromResult(Option.Some(input.Trim()));
public static Task<Option<string>> TryValidateAsync(string input)
{
return Task.FromResult(string.IsNullOrWhiteSpace(input)
? Option.None<string>()
: Option.Some(input.Trim()));
}
}
4 changes: 2 additions & 2 deletions samples/AStar.Dev.SampleBlazor/Components/Pages/Weather.razor
Original file line number Diff line number Diff line change
Expand Up @@ -56,12 +56,12 @@ else
}).ToArray();
}

private class WeatherForecast
private sealed class WeatherForecast
{
public DateOnly Date { get; set; }
public int TemperatureC { get; set; }
public string? Summary { get; set; }
public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
}

}
}
2 changes: 1 addition & 1 deletion samples/AStar.Dev.SampleBlazor/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,4 @@
app.MapRazorComponents<App>()
.AddInteractiveServerRenderMode();

app.Run();
await app.RunAsync();
26 changes: 13 additions & 13 deletions src/AStar.Dev.Functional.Extensions/OptionExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,19 +35,6 @@ public static Option<T> ToOption<T>(this T value)
: new Option<T>.Some(value);
}

/// <summary>
/// Enables deconstruction of an option into a boolean and value pair.
/// </summary>
/// <param name="option"></param>
/// <param name="isSome"></param>
/// <param name="value"></param>
/// <typeparam name="T"></typeparam>
public static void Deconstruct<T>(this Option<T> option, out bool isSome, out T? value)
{
isSome = option is Option<T>.Some;
value = isSome ? ((Option<T>.Some)option).Value : default;
}

/// <summary>
/// Converts a value to an <see cref="Option{T}" /> if it satisfies the predicate.
/// </summary>
Expand Down Expand Up @@ -143,4 +130,17 @@ public static T OrThrow<T>(this Option<T> option, Exception? ex = null)
{
return option is Option<T>.Some some ? some.Value : throw ex ?? new InvalidOperationException("No value present");
}

/// <summary>
/// Enables deconstruction of an option into a boolean and value pair.
/// </summary>
/// <param name="option"></param>
/// <param name="isSome"></param>
/// <param name="value"></param>
/// <typeparam name="T"></typeparam>
public static void Deconstruct<T>(this Option<T> option, out bool isSome, out T? value)
{
isSome = option is Option<T>.Some;
value = isSome ? ((Option<T>.Some)option).Value : default;
}
}
38 changes: 22 additions & 16 deletions src/AStar.Dev.Functional.Extensions/Option{T}.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,27 +12,15 @@ private Option()
{
}

/// <summary>
/// Overrides the ToString method to return both the type and, if present, the value.
/// </summary>
/// <returns></returns>
public override string ToString()
{
return this switch
{
Some some => $"Some({some.Value})",
None => "None",
_ => "Invalid"
};
}

/// <summary>
/// Implicitly converts a value to an <see cref="Option{T}" />.
/// </summary>
/// <param name="value">The value to wrap. Null becomes <see cref="None" />.</param>
public static implicit operator Option<T>(T value)
{
return value != null ? new Some(value) : None.Instance;
return value != null
? new Some(value)
: None.Instance;
}

/// <summary>
Expand Down Expand Up @@ -73,6 +61,15 @@ public Some(T value)
/// The wrapped value.
/// </summary>
public T Value { get; }

/// <summary>
/// Overrides the ToString method to return both the type and the value.
/// </summary>
/// <returns>The overridden ToString</returns>
public override string ToString()
{
return $"Some({Value})";
}
}

/// <summary>
Expand All @@ -81,12 +78,21 @@ public Some(T value)
public sealed class None : Option<T>
{
/// <summary>
/// A helper method to create an instance of <see cref="None" />
/// A helper method to create an instance of <see cref="Option{T}.None" />
/// </summary>
public static readonly None Instance = new ();

private None()
{
}

/// <summary>
/// Overrides the ToString method to return the type as a simple string.
/// </summary>
/// <returns>The overridden ToString</returns>
public override string ToString()
{
return "None";
}
}
}