Created
May 20, 2022 16:16
-
-
Save marcinnajder/d64afe842db3c92ae54add9bbe778f8d to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
async Optional<string> ProcessText(string text1, string text2) | |
{ | |
int number1 = await TryParseInt(text1); | |
int number2 = await TryParseInt(text2); | |
return (number1 + number2).ToString(); | |
} | |
Optional<int> TryParseInt(string text) => | |
int.TryParse(text, out var result) ? new Optional<int>(result) : Optional<int>.None; | |
// -- | |
public partial class Optional<T> | |
{ | |
public bool HasValue { get; } | |
public T Value { get; } | |
public Optional() => (HasValue, Value) = (false, default); | |
public Optional(T value) => (HasValue, Value) = (true, value); | |
public static Optional<T> None { get; } = new Optional<T>(); | |
} | |
// -- | |
[AsyncMethodBuilder(typeof(AsyncOptionalMethodBuilder<>))] | |
public partial class Optional<T> { } | |
public static class OptionalExtensions | |
{ | |
public static OptionalAwaiter<T> GetAwaiter<T>(this Optional<T> optional) => | |
new OptionalAwaiter<T>(optional); | |
} | |
internal interface IOptionalAwaiter | |
{ | |
bool HasValue { get; } | |
} | |
public class OptionalAwaiter<T> : INotifyCompletion, IOptionalAwaiter | |
{ | |
private Optional<T> optional; | |
public bool IsCompleted => this.optional.HasValue; | |
bool IOptionalAwaiter.HasValue => optional.HasValue; | |
public OptionalAwaiter(Optional<T> optional) => this.optional = optional; | |
public T GetResult() => optional.Value; | |
public void OnCompleted(Action continuation) { } | |
} | |
public class AsyncOptionalMethodBuilder<T> | |
{ | |
public static AsyncOptionalMethodBuilder<T> Create() => new AsyncOptionalMethodBuilder<T>(); | |
public void Start<TSM>(ref TSM stateMachine) where TSM : IAsyncStateMachine =>stateMachine.MoveNext(); | |
public Optional<T> Task { get; private set; } | |
public void SetResult(T result) => Task = new Optional<T>(result); | |
public void AwaitOnCompleted<TA, TSM>(ref TA awaiter, ref TSM stateMachine) | |
where TA : INotifyCompletion where TSM : IAsyncStateMachine | |
{ | |
if (awaiter is IOptionalAwaiter { HasValue: false }) | |
{ | |
Task = new Optional<T>(); | |
} | |
else | |
{ | |
awaiter.OnCompleted(stateMachine.MoveNext); | |
} | |
} | |
// empty methods | |
public void SetStateMachine(IAsyncStateMachine stateMachine) { } | |
public void SetException(Exception exception) { } | |
public void AwaitUnsafeOnCompleted<TA, TSM>(ref TA awaiter, ref TSM stateMachine) | |
where TA : ICriticalNotifyCompletion where TSM : IAsyncStateMachine { } | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment