Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save marcinnajder/d64afe842db3c92ae54add9bbe778f8d to your computer and use it in GitHub Desktop.
Save marcinnajder/d64afe842db3c92ae54add9bbe778f8d to your computer and use it in GitHub Desktop.
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