
рд╕рд╛рдорд╛рдиреНрдпреАрдХреГрдд async рд░рд┐рдЯрд░реНрди рдкреНрд░рдХрд╛рд░ - рдпрд╣ рдПрдХ рдирдпрд╛ C # 7 рдлреАрдЪрд░ рд╣реИ рдЬреЛ рди рдХреЗрд╡рд▓ рдЯрд╛рд╕реНрдХ рдХреЛ рдПрдХ рдкреНрд░рдХрд╛рд░ рдХреЗ рдПрд╕реНрдХрд┐рдВрд╕ рддрд░реАрдХреЛрдВ рдХреЗ рд░реВрдк рдореЗрдВ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИ, рдмрд▓реНрдХрд┐ рдЕрдиреНрдп рдкреНрд░рдХрд╛рд░ (рдХрдХреНрд╖рд╛рдПрдВ рдпрд╛ рд╕рдВрд░рдЪрдирд╛рдПрдВ) рднреА рд╣реИрдВ рдЬреЛ рдХреБрдЫ рд╡рд┐рд╢рд┐рд╖реНрдЯ рдЖрд╡рд╢реНрдпрдХрддрд╛рдУрдВ рдХреЛ рдкреВрд░рд╛ рдХрд░рддреА рд╣реИрдВред
рдЗрд╕реА рд╕рдордп, рдПрд╕рд┐рдВрдХреНрд╕ / рд╡реЗрдЯ рдХреБрдЫ рд╕рдВрджрд░реНрдн рдХреЗ рдЕрдВрджрд░ "рдирд┐рд░рдВрддрд░рддрд╛" рдХрд╛рд░реНрдпреЛрдВ рдХреЗ рдПрдХ рд╕реЗрдЯ рдХреЛ рдХреЙрд▓ рдХрд░рдиреЗ рдХрд╛ рдПрдХ рддрд░реАрдХрд╛ рд╣реИ рдЬреЛ рдПрдХ рдЕрдиреНрдп рдбрд┐рдЬрд╛рдЗрди рдкреИрдЯрд░реНрди рдХрд╛ рдПрдХ рд╕рд╛рд░ рд╣реИ - рдореЛрдирд╛рдб ред рддреЛ, рдХреНрдпрд╛ рд╣рдо рдПрдХ рдХреЛрдб рд▓рд┐рдЦрдиреЗ рдХреЗ рд▓рд┐рдП async / рд╡реЗрдЯ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдЬреЛ рдЙрд╕реА рддрд░рд╣ рд╕реЗ рд╡реНрдпрд╡рд╣рд╛рд░ рдХрд░реЗрдЧрд╛ рдЬреИрд╕реЗ рдХрд┐ рд╣рдо рд╕рд╛рдзреБрдУрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВ? рдпрд╣ рдкрддрд╛ рдЪрд▓рд╛ рд╣реИ рдХрд┐ - рд╣рд╛рдБ (рдХреБрдЫ рдЖрд░рдХреНрд╖рдгреЛрдВ рдХреЗ рд╕рд╛рде)ред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдиреАрдЪреЗ рджрд┐рдпрд╛ рдЧрдпрд╛ рдХреЛрдб рд╕рдВрдХрд▓рд┐рдд рдФрд░ рдХрд╛рдо рдХрд░ рд░рд╣рд╛ рд╣реИ:
async Task Main() { foreach (var s in new[] { "1,2", "3,7,1", null, "1" }) { var res = await Sum(s).GetMaybeResult(); Console.WriteLine(res.IsNothing ? "Nothing" : res.GetValue().ToString()); }
рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдореИрдВ рд╕рдордЭрд╛рдКрдВрдЧрд╛ рдХрд┐ рдХреЛрдб рдХреИрд╕реЗ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ ...
рд╕рд╛рдорд╛рдиреНрдпрдХреГрдд async рд░рд┐рдЯрд░реНрди рдкреНрд░рдХрд╛рд░
рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ рдЖрдЗрдП рдЬрд╛рдиреЗрдВ рдХрд┐ рд╣рдорд╛рд░реЗ рдЕрдкрдиреЗ рдкреНрд░рдХрд╛рд░ (рдЬреИрд╕реЗ MyAwaitable <T> ) рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХреНрдпрд╛ рдЖрд╡рд╢реНрдпрдХ рд╣реИ, рдЬрд┐рд╕рдХреЗ рдкрд░рд┐рдгрд╛рдорд╕реНрд╡рд░реВрдк рдХреБрдЫ рд╡рд┐рд╢реЗрд╖ рдкреНрд░рдХрд╛рд░ рдХреЗ рдлрд╝рдВрдХреНрд╢рди рд╣реЛрддреЗ рд╣реИрдВред рджрд╕реНрддрд╛рд╡реЗрдЬрд╝реАрдХрд░рдг рдХрд╣рддрд╛ рд╣реИ рдХрд┐ рдЗрд╕ рдкреНрд░рдХрд╛рд░ рдХрд╛ рд╣реЛрдирд╛ рдЖрд╡рд╢реНрдпрдХ рд╣реИ:
GetAwaiter () рд╡рд┐рдзрд┐ рдЬреЛ рдПрдХ рдкреНрд░рдХрд╛рд░ рдХреА рдПрдХ рд╡рд╕реНрддреБ рд▓реМрдЯрд╛рддреА рд╣реИ рдЬреЛ INotifyCompletion рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рддреА рд╣реИ рдФрд░ рдЬрд┐рд╕рдХреЗ рдкрд╛рд╕ IsCompleted property рдФрд░ T GetResult () рдореЗрдердб рд╣реИ;
[AsyncMethodBuilder (рдкреНрд░рдХрд╛рд░)] рд╡рд┐рд╢реЗрд╖рддрд╛ рдЬреЛ "рд╡рд┐рдзрд┐ рдирд┐рд░реНрдорд╛рддрд╛" рд╡рд░реНрдЧ ( рдпрд╛ рд╕рдВрд░рдЪрдирд╛ ) рдХреЛ рдЗрдВрдЧрд┐рдд рдХрд░рддрд╛ рд╣реИ рдЬреИрд╕реЗ MyAwaitableTaskMethodBuilder <T> рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рд╡рд┐рдзрд┐рдпреЛрдВ рдХреЗ рд╕рд╛рде:
- рд╕реНрдерд┐рд░ рдмрдирд╛рдПрдБ ()
- рдкреНрд░рд╛рд░рдВрдн (рд░рд╛рдЬреНрдпрдордВрдЪ)
- SetResult (рдкрд░рд┐рдгрд╛рдо)
- SetException (рдЕрдкрд╡рд╛рдж)
- SetStateMachine (StateMachine)
- рдкреНрд░рддреАрдХреНрд╖рд╛рд░рдд (рдкреНрд░рддреАрдХреНрд╖рд╛рд░рдд, рд░рд╛рдЬреНрдпрдордВрдЪ)
- AwaitUnsafeOnCompleted (рдкреНрд░рддреАрдХреНрд╖рд╛рдХрд░реНрддрд╛, рд░рд╛рдЬреНрдпрдорд╢реАрди)
- рдХрд╛рд░реНрдп
рдпрд╣рд╛рдБ MyAwaitable рдФрд░ MyAwaitableTaskMethodBuilder рдХрд╛ рдПрдХ рд╕рд░рд▓ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рд╣реИ [AsyncMethodBuilder(typeof(MyAwaitableTaskMethodBuilder<>))] public class MyAwaitable<T> : INotifyCompletion { private Action _continuation; public MyAwaitable() { } public MyAwaitable(T value) { this.Value = value; this.IsCompleted = true; } public MyAwaitable<T> GetAwaiter() => this; public bool IsCompleted { get; private set; } public T Value { get; private set; } public Exception Exception { get; private set; } public T GetResult() { if (!this.IsCompleted) throw new Exception("Not completed"); if (this.Exception != null) { ExceptionDispatchInfo.Throw(this.Exception); } return this.Value; } internal void SetResult(T value) { if (this.IsCompleted) throw new Exception("Already completed"); this.Value = value; this.IsCompleted = true; this._continuation?.Invoke(); } internal void SetException(Exception exception) { this.IsCompleted = true; this.Exception = exception; } void INotifyCompletion.OnCompleted(Action continuation) { this._continuation = continuation; if (this.IsCompleted) { continuation(); } } } public class MyAwaitableTaskMethodBuilder<T> { public MyAwaitableTaskMethodBuilder() => this.Task = new MyAwaitable<T>(); public static MyAwaitableTaskMethodBuilder<T> Create() => new MyAwaitableTaskMethodBuilder<T>(); public void Start<TStateMachine>(ref TStateMachine stateMachine) where TStateMachine : IAsyncStateMachine => stateMachine.MoveNext(); public void SetStateMachine(IAsyncStateMachine stateMachine) { } public void SetException(Exception exception) => this.Task.SetException(exception); public void SetResult(T result) => this.Task.SetResult(result); public void AwaitOnCompleted<TAwaiter, TStateMachine>( ref TAwaiter awaiter, ref TStateMachine stateMachine) where TAwaiter : INotifyCompletion where TStateMachine : IAsyncStateMachine => this.GenericAwaitOnCompleted(ref awaiter, ref stateMachine); public void AwaitUnsafeOnCompleted<TAwaiter, TStateMachine>( ref TAwaiter awaiter, ref TStateMachine stateMachine) where TAwaiter : ICriticalNotifyCompletion where TStateMachine : IAsyncStateMachine => this.GenericAwaitOnCompleted(ref awaiter, ref stateMachine); public void GenericAwaitOnCompleted<TAwaiter, TStateMachine>( ref TAwaiter awaiter, ref TStateMachine stateMachine) where TAwaiter : INotifyCompletion where TStateMachine : IAsyncStateMachine => awaiter.OnCompleted(stateMachine.MoveNext); public MyAwaitable<T> Task { get; } }
рдЕрдм рд╣рдо MyAwaitable рдХреЛ async рд╡рд┐рдзрд┐рдпреЛрдВ рдХреЗ рдкрд░рд┐рдгрд╛рдорд╕реНрд╡рд░реВрдк рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ:
private async MyAwaitable<int> MyAwaitableMethod() { int result = 0; int arg1 = await this.GetMyAwaitable(1); result += arg1; int arg2 = await this.GetMyAwaitable(2); result += arg2; int arg3 = await this.GetMyAwaitable(3); result += arg3; return result; } private async MyAwaitable<int> GetMyAwaitable(int arg) { await Task.Delay(1);
рдХреЛрдб рдЕрдкреЗрдХреНрд╖рд┐рдд рд░реВрдк рд╕реЗ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ рд▓реЗрдХрд┐рди MyAwaitable рдХреЛ рдЖрд╡рд╢реНрдпрдХрддрд╛рдУрдВ рдХреЗ рдПрдХ рдЙрджреНрджреЗрд╢реНрдп рдХреЛ рд╕рдордЭрдиреЗ рдХреЗ рд▓рд┐рдП рдЖрдЗрдП рдПрдХ рдирдЬрд╝рд░ рдбрд╛рд▓рддреЗ рд╣реИрдВ рдХрд┐ C # рдкреНрд░реАрдкреНрд░реЛрд╕реЗрд╕рд░ MyAwaitableMethod рдХреЗ рд╕рд╛рде рдХреНрдпрд╛ рдХрд░рддрд╛ рд╣реИред рдпрджрд┐ рдЖрдк рдХреБрдЫ рдбреА-рд╕рдВрдХрд▓рди рдЙрдкрдпреЛрдЧ (рдЬреИрд╕реЗ рдбреЙрдЯрдкреЗрдХ) рдЪрд▓рд╛рддреЗ рд╣реИрдВ, рддреЛ рдЖрдк рджреЗрдЦреЗрдВрдЧреЗ рдХрд┐ рдореВрд▓ рд╡рд┐рдзрд┐ рдирд┐рдореНрдирд╛рдиреБрд╕рд╛рд░ рдмрджрд▓ рджреА рдЧрдИ рдереА:
private MyAwaitable<int> MyAwaitableMethod() { var stateMachine = new MyAwaitableMethodStateMachine(); stateMachine.Owner = this; stateMachine.Builder = MyAwaitableTaskMethodBuilder<int>.Create(); stateMachine.State = 0; stateMachine.Builder.Start(ref stateMachine); return stateMachine.Builder.Task; }
MyAwaitableMethodStateMachineрджрд░рдЕрд╕рд▓, рдпрд╣ рдПрдХ рд╕рд░рд▓реАрдХреГрдд рдХреЛрдб рд╣реИ рдЬрд╣рд╛рдВ рдореИрдВ рдПрдХ рд╕рдВрдХрд▓рд┐рдд рдХреЛрдб рдХреЛ рдкрдардиреАрдп рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдмрд╣реБрдд рд╕рд╛рд░реЗ рдЕрдиреБрдХреВрд▓рди рдЫреЛрдбрд╝ рджреЗрддрд╛ рд╣реВрдВ
sealed class MyAwaitableMethodStateMachine : IAsyncStateMachine { public int State; public MyAwaitableTaskMethodBuilder<int> Builder; public BuilderDemo Owner; private int _result; private int _arg1; private int _arg2; private int _arg3; private MyAwaitableAwaiter<int> _awaiter1; private MyAwaitableAwaiter<int> _awaiter2; private MyAwaitableAwaiter<int> _awaiter3; private void SetAwaitCompletion(INotifyCompletion awaiter) { var stateMachine = this; this.Builder.AwaitOnCompleted(ref awaiter, ref stateMachine); } void IAsyncStateMachine.MoveNext() { int finalResult; try { label_begin: switch (this.State) { case 0: this._result = 0; this._awaiter1 = this.Owner.GetMyAwaitable(1).GetAwaiter(); this.State = 1; if (!this._awaiter1.IsCompleted) { this.SetAwaitCompletion(this._awaiter1); return; } goto label_begin; case 1:
рдЙрддреНрдкрдиреНрди рдХреЛрдб рдХреА рд╕рдореАрдХреНрд╖рд╛ рдХрд░рддреЗ рд╣реБрдП рд╣рдо рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВ рдХрд┐ "рдореЗрдердб рдмрд┐рд▓реНрдбрд░" рдХреА рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдЬрд┐рдореНрдореЗрджрд╛рд░рд┐рдпрд╛рдБ рд╣реИрдВ:
- рдПрдХ рдмрдЪреНрдЪреЗ рдХреЗ рдЕрддреБрд▓реНрдпрдХрд╛рд▓рд┐рдХ рдСрдкрд░реЗрд╢рди рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рдЬрдм рд░рд╛рдЬреНрдп рдорд╢реАрди MoveNext () рд╡рд┐рдзрд┐ рдХреЙрд▓ рд╢реЗрдбреНрдпреВрд▓рд┐рдВрдЧ (рд╕рдмрд╕реЗ рд╕рд░рд▓ рдкрд░рд┐рджреГрд╢реНрдп рдореЗрдВ рд╣рдо рд╕рд┐рд░реНрдл MoveNext () OnCompleted ( async рдСрдкрд░реЗрд╢рди рд╡реЗрдЯрд░ рдХреЗ) рдореЗрдВ рдкрд╛рд╕ рдХрд░рддреЗ рд╣реИрдВред
- рдПрдХ рдЕрддреБрд▓реНрдпрдХрд╛рд▓рд┐рдХ рдСрдкрд░реЗрд╢рди рд╕рдВрджрд░реНрдн рд╡рд╕реНрддреБ рдХрд╛ рдирд┐рд░реНрдорд╛рдг (
public MyAwaitable<T> Task { get; }
) - рдЙрддреНрдкрдиреНрди рд░рд╛рдЬреНрдп рдорд╢реАрдиреЛрдВ рдХреЗ рдЕрдВрддрд┐рдо рд░рд╛рдЬреНрдпреЛрдВ рдкрд░ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛: SetResult рдпрд╛ SetException ред
рджреВрд╕рд░реЗ рд╢рдмреНрджреЛрдВ рдореЗрдВ, "рд╡рд┐рдзрд┐ рдмрд┐рд▓реНрдбрд░реЛрдВ" рдХреЗ рд╕рд╛рде рд╣рдо рдЗрд╕ рдкрд░ рдирд┐рдпрдВрддреНрд░рдг рдкрд╛ рд╕рдХрддреЗ рд╣реИрдВ рдХрд┐ рдХреИрд╕реЗ рдЕрддреБрд▓реНрдпрдХрд╛рд▓рд┐рдХ рддрд░реАрдХреЛрдВ рдХреЛ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рдФрд░ рдпрд╣ рдПрдХ рдРрд╕реА рд╕реБрд╡рд┐рдзрд╛ рдХреА рддрд░рд╣ рджрд┐рдЦрддрд╛ рд╣реИ рдЬреЛ рд╣рдореЗрдВ рдЕрдкрдиреЗ рд▓рдХреНрд╖реНрдп рдХреЛ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдореЗрдВ рдорджрдж рдХрд░реЗрдЧрд╛ - рд╢рд╛рдпрдж рдореЛрдирдб рд╡реНрдпрд╡рд╣рд╛рд░ рдХрд╛ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрдиред рд▓реЗрдХрд┐рди рдЙрд╕ рд╕рдиреНрдпрд╛рд╕реА рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдХреНрдпрд╛ рдЕрдЪреНрдЫрд╛ рд╣реИ? рдЦреИрд░ ... рдЖрдк рдЗрдВрдЯрд░рдиреЗрдЯ рдореЗрдВ рдЙрд╕ рд╕рдиреНрдпрд╛рд╕реА рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдмрд╣реБрдд рд╕рд╛рд░реЗ рд▓реЗрдЦ рдкрд╛ рд╕рдХрддреЗ рд╣реИрдВ, рдЗрд╕рд▓рд┐рдП рдпрд╣рд╛рдВ рдореИрдВ рд╕рд┐рд░реНрдл рдореВрд▓ рдмрд╛рддреЗрдВ рдмрддрд╛рдКрдВрдЧрд╛ред
рд╢рд╛рдпрдж рдореЛрдирдж
рд╕рдВрдХреНрд╖реЗрдк рдореЗрдВ, рд╢рд╛рдпрдж рдореЛрдирдб рдПрдХ рдбрд┐рдЬрд╝рд╛рдЗрди рдкреИрдЯрд░реНрди рд╣реИ рдЬреЛ рдлрд╝рдВрдХреНрд╢рди рдХреЙрд▓ рд╢реНрд░реГрдВрдЦрд▓рд╛ рдореЗрдВ рд░реБрдХрд╛рд╡рдЯ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИ рдпрджрд┐ рд╢реНрд░реГрдВрдЦрд▓рд╛ рд╕реЗ рдХреБрдЫ рдлрд╝рдВрдХреНрд╢рди рдПрдХ рдореВрд▓реНрдпрд╡рд╛рди рдкрд░рд┐рдгрд╛рдо (рдЬреИрд╕реЗ рдкрд╛рд░реНрд╕рд┐рдВрдЧ рддреНрд░реБрдЯрд┐) рдЙрддреНрдкрдиреНрди рдирд╣реАрдВ рдХрд░ рд╕рдХрддрд╛ рд╣реИред
рдРрддрд┐рд╣рд╛рд╕рд┐рдХ рд░реВрдк рд╕реЗ, рдЕрдирд┐рд╡рд╛рд░реНрдп рдкреНрд░реЛрдЧреНрд░рд╛рдорд┐рдВрдЧ рднрд╛рд╖рд╛рдПрдВ рджреЛ рддрд░реАрдХреЛрдВ рд╕реЗ рд╕рдорд╕реНрдпрд╛ рдХрд╛ рд╕рдорд╛рдзрд╛рди рдХрд░ рд░рд╣реА рд╣реИрдВ:
- рд╕рд╢рд░реНрдд рддрд░реНрдХ рдХреА рдмрд╣реБрдд
- рдЕрдкрд╡рд╛рдж
рджреЛрдиреЛрдВ рддрд░реАрдХреЛрдВ рд╕реЗ рд╕реНрдкрд╖реНрдЯ рдиреБрдХрд╕рд╛рди рд╣реИрдВ, рдЗрд╕рд▓рд┐рдП рдПрдХ рддреАрд╕рд░реЗ рддрд░реАрдХреЗ рдХрд╛ рдЖрд╡рд┐рд╖реНрдХрд╛рд░ рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛:
- рдПрдХ рдкреНрд░рдХрд╛рд░ рдмрдирд╛рдПрдВ рдЬреЛ 2 рд░рд╛рдЬреНрдпреЛрдВ рдореЗрдВ рд╣реЛ рд╕рдХрддрд╛ рд╣реИ: "рдХреБрдЫ рдореВрд▓реНрдп" рдФрд░ "рдХреБрдЫ рдирд╣реАрдВ" - рдЪрд▓реЛ рдЗрд╕реЗ "рд╢рд╛рдпрдж" рдХрд╣рддреЗ рд╣реИрдВ
- рдПрдХ рдлрд╝рдВрдХреНрд╢рди рдмрдирд╛рдПрдВ (рдЗрд╕реЗ "SelectMany" рдХрд╣рддреЗ рд╣реИрдВ) рдЬреЛ 2 рддрд░реНрдХ рджреЗрддрд╛ рд╣реИ:
2.1ред "рд╢рд╛рдпрдж" рдкреНрд░рдХрд╛рд░ рдХреА рдПрдХ рд╡рд╕реНрддреБ
2.2ред рдХреЙрд▓ рд╕реЗрдЯ рд╕реЗ рдПрдХ рдЕрдЧрд▓рд╛ рдлрд╝рдВрдХреНрд╢рди - рдлрд╝рдВрдХреНрд╢рди рдХреЛ "рд╢рд╛рдпрдж" рдХрд╛ рдПрдХ рдСрдмреНрдЬреЗрдХреНрдЯ рднреА рд╡рд╛рдкрд╕ рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдП, рдЬрд┐рд╕рдореЗрдВ рдПрдХ рдкрд░рд┐рдгрд╛рдо рдпрд╛ "рдХреБрдЫ рднреА рдирд╣реАрдВ" рд╣реЛрдЧрд╛ рдпрджрд┐ рдЗрд╕рдХрд╛ рдкрд░рд┐рдгрд╛рдо рдореВрд▓реНрдпрд╛рдВрдХрди рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ (рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП рдлрд╝рдВрдХреНрд╢рди рдкреИрд░рд╛рдореАрдЯрд░ рд╕рд╣реА рдкреНрд░рд╛рд░реВрдк рдореЗрдВ рдирд╣реАрдВ рд╣реИрдВ) - "SelectMany" рдлрд╝рдВрдХреНрд╢рди рдЬрд╛рдБрдЪрддрд╛ рд╣реИ рдХрд┐ "рд╢рд╛рдпрдж" рдХрд╛ рдХреБрдЫ рдореВрд▓реНрдп рд╣реИ рдФрд░ рдлрд┐рд░ рдЕрдЧрд▓реЗ рдлрд╝рдВрдХреНрд╢рди рдХреЛ рдПрдХ рддрд░реНрдХ рдХреЗ рд░реВрдк рдореЗрдВ рдорд╛рди ("рд╢рд╛рдпрдж" рд╕реЗ рдирд┐рдХрд╛рд▓рд╛ рдЧрдпрд╛) рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдХреЙрд▓ рдХрд░рддрд╛ рд╣реИ рдФрд░ рдлрд┐рд░ рдЕрдкрдирд╛ рдкрд░рд┐рдгрд╛рдо рджреЗрддрд╛ рд╣реИ, рдЕрдиреНрдпрдерд╛ рдпрд╣ "рдХреБрдЫ рднреА рдирд╣реАрдВ" рд╕реНрдерд┐рддрд┐ рдореЗрдВ "рд╢рд╛рдпрдж" рд╡рд╕реНрддреБ рджреЗрддрд╛ рд╣реИ ред

C # рдореЗрдВ рдЗрд╕реЗ рдЗрд╕ рддрд░рд╣ рд▓рд╛рдЧреВ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ:
public struct Maybe<T> { public static implicit operator Maybe<T>(T value) => Value(value); public static Maybe<T> Value(T value) => new Maybe<T>(false, value); public static readonly Maybe<T> Nothing = new Maybe<T>(true, default); private Maybe(bool isNothing, T value) { this.IsNothing = isNothing; this._value = value; } public readonly bool IsNothing; private readonly T _value; public T GetValue() => this.IsNothing ? throw new Exception("Nothing") : this._value; } public static class MaybeExtensions { public static Maybe<TRes> SelectMany<TIn, TRes>( this Maybe<TIn> source, Func<TIn, Maybe<TRes>> func) => source.IsNothing ? Maybe<TRes>.Nothing : func(source.GetValue()); }
рдФрд░ рдЙрдкрдпреЛрдЧ:
static void Main() { for (int i = 0; i < 10; i++) { var res = Function1(i).SelectMany(Function2).SelectMany(Function3); Console.WriteLine(res.IsNothing ? "Nothing" : res.GetValue().ToString()); } Maybe<int> Function1(int acc) => acc < 10 ? acc + 1 : Maybe<int>.Nothing; Maybe<int> Function2(int acc) => acc < 10 ? acc + 2 : Maybe<int>.Nothing; Maybe<int> Function3(int acc) => acc < 10 ? acc + 3 : Maybe<int>.Nothing; }
рдХреНрдпреЛрдВ 'SelectMany'?рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдЖрдк рдореЗрдВ рд╕реЗ рдХреБрдЫ рдПрдХ рд╕рд╡рд╛рд▓ рдкреВрдЫ рд╕рдХрддреЗ рд╣реИрдВ: "рд▓реЗрдЦрдХ рдиреЗ рдлрд╝рдВрдХреНрд╢рди рдХреЛ" SelectMany "рдХреНрдпреЛрдВ рдХрд╣рд╛? рдпрд╣ рдмрд╣реБрдд рдЕрдЬреАрдм рдирд╛рдо рд╣реИ"ред рдпрд╣ рд╣реИ, рд▓реЗрдХрд┐рди рдЙрд╕рдХреЗ рд▓рд┐рдП рдПрдХ рдХрд╛рд░рдг рд╣реИред C # рдореЗрдВ SelectMany рдХрд╛ рдЙрдкрдпреЛрдЧ рдкреНрд░реАрдкреНрд░реЛрд╕реЗрд╕рд░ рджреНрд╡рд╛рд░рд╛ рдХреНрд╡реЗрд░реА рдиреЛрдЯреЗрд╢рди рдХрд╛ рд╕рдорд░реНрдерди рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рдЬреЛ рдХреЙрд▓ рдЪреЗрди рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдирд╛ рд╕рд░рд▓ рдХрд░рддрд╛ рд╣реИ (рдЖрдк рдореЗрд░реЗ рдкрд┐рдЫрд▓реЗ рд▓реЗрдЦ рдореЗрдВ рдЕрдзрд┐рдХ рд╡рд┐рд╡рд░рдг рдкрд╛ рд╕рдХрддреЗ рд╣реИрдВ)ред
рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ, рд╣рдо рдХреЙрд▓ рдЪреЗрди рдХреЛ рдирд┐рдореНрдирд╛рдиреБрд╕рд╛рд░ рдмрджрд▓ рд╕рдХрддреЗ рд╣реИрдВ:
var res = Function1(i) .SelectMany(x2 => Function2(x2).SelectMany(x3 => Function3(x3.SelectMany<int, int>(x4 => x2 + x3 + x4)));
рддрд╛рдХрд┐ рд╣рдо рд╕рднреА рдордзреНрдпрд╡рд░реНрддреА рдкрд░рд┐рдгрд╛рдореЛрдВ рддрдХ рдкрд╣реБрдБрдЪ рдкреНрд░рд╛рдкреНрдд рдХрд░ рд╕рдХреЗрдВ рдЬреЛ рд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ рд╣реИ рд▓реЗрдХрд┐рди рдХреЛрдб рдХреЛ рдкрдврд╝рдирд╛ рдореБрд╢реНрдХрд┐рд▓ рд╣реИред
рдпрд╣рд╛рдБ рдХреНрд╡реЗрд░реА рдиреЛрдЯреЗрд╢рди рд╣рдорд╛рд░реА рдорджрдж рдХрд░рддрд╛ рд╣реИ:
var res = from x2 in Function1(i) from x3 in Function2(x2) from x4 in Function3(x3) select x2 + x3 + x4;
рдХреЛрдб рдХреЛ рдЕрдирд┐рд╡рд╛рд░реНрдп рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП рд╣рдореЗрдВ "рдХрдИ рдХрд╛ рдЪрдпрди рдХрд░реЗрдВ" рдХреЗ рдПрдХ рдмрдврд╝рд╛рдпрд╛ рд╕рдВрд╕реНрдХрд░рдг рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ
public static Maybe<TJ> SelectMany<TIn, TRes, TJ>( this Maybe<TIn> source, Func<TIn, Maybe<TRes>> func, Func<TIn, TRes, TJ> joinFunc) { if (source.IsNothing) return Maybe<TJ>.Nothing; var res = func(source.GetValue()); return res.IsNothing ? Maybe<TJ>.Nothing : joinFunc(source.GetValue(), res.GetValue()); }
рдЖрдЗрдП рдЗрд╕ 'рд╢рд╛рд╕реНрддреНрд░реАрдп' рд╢рд╛рдпрдж 'рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рд▓реЗрдЦ рд╣реЗрдбрд░ рд╕реЗ рдкреНрд░реЛрдЧреНрд░рд╛рдо рдХреЛ рд▓рд╛рдЧреВ рдХрд░реЗрдВ static void Main() { foreach (var s in new[] {"1,2", "3,7,1", null, "1"}) { var res = Sum(s); Console.WriteLine(res.IsNothing ? "Nothing" : res.GetValue().ToString()); } Console.ReadKey(); } static Maybe<int> Sum(string input) => Split(input).SelectMany(items => Acc(0, 0, items));
рдХреЛрдб рдмрд╣реБрдд рдЕрдЪреНрдЫрд╛ рдирд╣реАрдВ рд▓рдЧрддрд╛ рдХреНрдпреЛрдВрдХрд┐ C # рдХреЛ рдПрдХ рдХрд╛рд░реНрдпрд╛рддреНрдордХ рднрд╛рд╖рд╛ рдХреЗ рд░реВрдк рдореЗрдВ рдирд╣реАрдВ рдмрдирд╛рдпрд╛ рдЧрдпрд╛ рдерд╛, рд▓реЗрдХрд┐рди "рд╕рдЪ" рдХрд╛рд░реНрдпрд╛рддреНрдордХ рднрд╛рд╖рд╛рдУрдВ рдореЗрдВ рдЬреИрд╕реЗ рд╣рд╛рд╕реНрдХреЗрд▓ рдЬреИрд╕реЗ рджреГрд╖реНрдЯрд┐рдХреЛрдг рдмрд╣реБрдд рдЖрдо рд╣реИрдВ
Async рд╣реЛ рд╕рдХрддрд╛ рд╣реИ
рд╢рд╛рдпрдж рдореЛрдирдб рдХрд╛ рд╕рд╛рд░ рдПрдХ рдлрд╝рдВрдХреНрд╢рди рдХреЙрд▓ рд╢реНрд░реГрдВрдЦрд▓рд╛ рдХреЛ рдирд┐рдпрдВрддреНрд░рд┐рдд рдХрд░рдирд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдпрд╣ рдареАрдХ рд╣реИ рдХрд┐ "async / рдкреНрд░рддреАрдХреНрд╖рд╛" рдХрд░рддрд╛ рд╣реИред рддреЛ рдЪрд▓реЛ рдЙрдиреНрд╣реЗрдВ рдПрдХ рд╕рд╛рде рд╕рдВрдпреЛрдЬрд┐рдд рдХрд░рдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд░реЗрдВред рдкрд╣рд▓реЗ, рд╣рдореЗрдВ рдЕрддреБрд▓реНрдпрдХрд╛рд▓рд┐рдХ рдХрд╛рд░реНрдпреЛрдВ рдХреЗ рд╕рд╛рде рд╕рдВрдЧрдд рдкреНрд░рдХрд╛рд░ рдмрдирд╛рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ рдФрд░ рд╣рдо рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдЬрд╛рдирддреЗ рд╣реИрдВ рдХрд┐ рдпрд╣ рдХреИрд╕реЗ рдХрд░рдирд╛ рд╣реИ:
[AsyncMethodBuilder(typeof(MaybeTaskMethodBuilder<>))] public class Maybe<T> : INotifyCompletion { ... public Maybe<T> GetAwaiter() => this; public bool IsCompleted { get; private set; } public void OnCompleted(Action continuation){...} public T GetResult() =>... }
рдЕрдм рдЖрдЗрдП рдПрдХ рдирдЬрд╝рд░ рдбрд╛рд▓рддреЗ рд╣реИрдВ рдХрд┐ "рд╢рд╛рд╕реНрддреНрд░реАрдп рд╣реЛ рд╕рдХрддрд╛ рд╣реИ" рдХреЛ рдХрд┐рд╕реА рднреА рд╕рдорд╛рдирддрд╛ рдХреЛ рдЦреЛрдЬрдиреЗ рдореЗрдВ рд╕рдХреНрд╖рдо рд╣реЛрдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рд░рд╛рдЬреНрдп рдорд╢реАрди рдХреЗ рд░реВрдк рдореЗрдВ рдХреИрд╕реЗ рд▓рд┐рдЦрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ:
static void Main() { for (int i = 0; i < 10; i++) { var stateMachine = new StateMachine(); stateMachine.state = 0; stateMachine.i = i; stateMachine.MoveNext(); var res = stateMachine.Result; Console.WriteLine(res.IsNothing ? "Nothing" : res.GetValue().ToString()); } Console.ReadKey(); } class StateMachine { public int state = 0; public int i; public Maybe<int> Result; private Maybe<int> _f1; private Maybe<int> _f2; private Maybe<int> _f3; public void MoveNext() { label_begin: switch (this.state) { case 0: this._f1 = Function1(this.i); this.state = Match ? -1 : 1; goto label_begin; case 1: this._f2 = Function2(this._f1.GetValue()); this.state = this._f2.IsNothing ? -1 : 2; goto label_begin; case 2: this._f3 = Function3(this._f2.GetValue()); this.state = this._f3.IsNothing ? -1 : 3; goto label_begin; case 3: this.Result = this._f3.GetValue(); break; case -1: this.Result = Maybe<int>.Nothing; break; } } }
рдпрджрд┐ рд╣рдо рдЗрд╕ рд░рд╛рдЬреНрдп рдорд╢реАрди рдХреЛ C # рдкреНрд░реАрдкреНрд░реЛрд╕реЗрд╕рд░ рдПрдХ (рдКрдкрд░ рджреЗрдЦреЗрдВ - 'MyAwaitableMethodStateMachine' рджреНрд╡рд╛рд░рд╛ рдЬрдирд░реЗрдЯ рдХрд░рддреЗ рд╣реИрдВ) рдХреЗ рд╕рд╛рде рдореЗрд▓ рдЦрд╛рддреЗ рд╣реИрдВ, рддреЛ рд╣рдо рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВ рдХрд┐ рд╢рд╛рдпрдж рд░рд╛рдЬреНрдп рдХреА рдЬрд╛рдБрдЪ рдЕрдВрджрд░ рд▓рд╛рдЧреВ рдХреА рдЬрд╛ рд╕рдХрддреА рд╣реИ:
this.Builder.AwaitOnCompleted(ref awaiter, ref stateMachine);
рдЬрд╣рд╛рдБ ref awaiter
рд╢рд╛рдпрдж рдПрдХ рдкреНрд░рдХрд╛рд░ рдХреА рд╡рд╕реНрддреБ рд╣реИред рдпрд╣рд╛рдВ рдПрдХрдорд╛рддреНрд░ рд╕рдорд╕реНрдпрд╛ рдпрд╣ рд╣реИ рдХрд┐ рд╣рдо рдорд╢реАрди рдХреЛ "рдЕрдВрддрд┐рдо" (-1) рд╕реНрдерд┐рддрд┐ рдореЗрдВ рд╕реЗрдЯ рдирд╣реАрдВ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рдЗрд╕рдХрд╛ рдорддрд▓рдм рдпрд╣ рд╣реИ рдХрд┐ рд╣рдо рдирд┐рд╖реНрдкрд╛рджрди рдкреНрд░рд╡рд╛рд╣ рдХреЛ рдирд┐рдпрдВрддреНрд░рд┐рдд рдирд╣реАрдВ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ? рджрд░рдЕрд╕рд▓, рдРрд╕рд╛ рдирд╣реАрдВ рд╣реИред рдмрд╛рдд рдпрд╣ рд╣реИ рдХрд┐ рдкреНрд░рддреНрдпреЗрдХ рдЕрддреБрд▓реНрдпрдХрд╛рд▓рд┐рдХ рдХрд╛рд░реНрд░рд╡рд╛рдИ рдХреЗ рд▓рд┐рдП C # рдХреЙрд▓рдмреИрдХ рдПрдХреНрд╢рди рдЧрд░реНрдд рд╕реЗрдЯ рдХрд░рддрд╛ рд╣реИ INotifyCompletion рдЗрдВрдЯрд░рдлрд╝реЗрд╕, рдЗрд╕рд▓рд┐рдП рдпрджрд┐ рд╣рдо рдПрдХ рдирд┐рд╖реНрдкрд╛рджрди рдкреНрд░рд╡рд╛рд╣ рдХреЛ рддреЛрдбрд╝рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ рддреЛ рд╣рдо рдХреЙрд▓рдмреИрдХ рдПрдХреНрд╢рди рдХреЛ рдПрдХ рдорд╛рдорд▓реЗ рдореЗрдВ рдХреЙрд▓ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдЬрдм рд╣рдо рдкреНрд░рд╡рд╛рд╣ рдХреЛ рдЬрд╛рд░реА рдирд╣реАрдВ рд░рдЦ рд╕рдХрддреЗред
рдпрд╣рд╛рдВ рдПрдХ рдФрд░ рдЪреБрдиреМрддреА рдпрд╣ рд╣реИ рдХрд┐ рдЙрддреНрдкрдиреНрди рд░рд╛рдЬреНрдп рдорд╢реАрди рдПрдХ рд╡рд░реНрддрдорд╛рди рдкреНрд░рд╡рд╛рд╣ рдХреЗ рд░реВрдк рдореЗрдВ рдПрдХ рдЕрдЧрд▓реА рдХрд╛рд░реНрд░рд╡рд╛рдИ (рдПрдХ рдирд┐рд░рдВрддрд░рддрд╛ рдХреЙрд▓рдмреИрдХ рдХреЗ рд░реВрдк рдореЗрдВ) рдЧреБрдЬрд░рддреА рд╣реИ, рд▓реЗрдХрд┐рди рд╣рдореЗрдВ рдкреНрд░рд╛рд░рдВрднрд┐рдХ рдкреНрд░рд╡рд╛рд╣ рдХреЗ рдирд┐рд░рдВрддрд░рддрд╛ рдХреЙрд▓рдмреИрдХ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИ рдЬреЛ рдХрд┐ рдПрд╕реНрдХрд┐рдВрд╕ рд╕рдВрдЪрд╛рд▓рди рдХреЗ рдмрд╛рдХреА рд╣рд┐рд╕реНрд╕реЛрдВ рдХреЛ рджрд░рдХрд┐рдирд╛рд░ рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрдЧрд╛:

рдЗрд╕рд▓рд┐рдП, рд╣рдореЗрдВ рдХрд┐рд╕реА рддрд░рд╣ рд╕реЗ рдЕрдкрдиреЗ рдкреВрд░реНрд╡рдЬреЛрдВ рдХреЗ рд╕рд╛рде рдПрдХ рдмрдЪреНрдЪреЗ рдХреЛ рдПрд╕реНрдХреЙрди рдХрд╛рд░реНрд░рд╡рд╛рдИ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рд╣рдо рдЕрдкрдиреЗ "рдореЗрдердб рдмрд┐рд▓реНрдбрд░" рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рдЬрд┐рд╕рдореЗрдВ рдПрдХ рд╡рд░реНрддрдорд╛рди async рдСрдкрд░реЗрд╢рди рдХрд╛ рд▓рд┐рдВрдХ рд╣реИ - рдХрд╛рд░реНрдп ред рд╕рднреА рдЪрд╛рдЗрд▓реНрдб async рдСрдкрд░реЗрд╢рдВрд╕ рдХреЗ рд▓рд┐рдВрдХ AwaitOnCompleted(ref awaiter
рд░реВрдк рдореЗрдВ AwaitOnCompleted(ref awaiter
рдореЗрдВ рдкрд╛рд╕ рдХрд┐рдП рдЬрд╛рдПрдВрдЧреЗ , рдЗрд╕рд▓рд┐рдП рд╣рдореЗрдВ рдмрд╕ рдпрд╣ рдЬрд╛рдВрдЪрдиреЗ рдХреА рдЬрд╝рд░реВрд░рдд рд╣реИ рдХрд┐ рдХреНрдпрд╛ рдкреИрд░рд╛рдореАрдЯрд░ рд╢рд╛рдпрдж рдПрдХ рдЙрджрд╛рд╣рд░рдг рд╣реИ рдФрд░ рдпрджрд┐ рдпрд╣ рд╡рд░реНрддрдорд╛рди рд╕реЗрдЯ рд╣реИ рддреЛ рд╢рд╛рдпрдж рдмрдЪреНрдЪреЗ рдХреЗ рд▓рд┐рдП рдорд╛рддрд╛-рдкрд┐рддрд╛ рдХреЗ рд░реВрдк рдореЗрдВред
[AsyncMethodBuilder(typeof(MaybeTaskMethodBuilder<>))] public class Maybe<T> : IMaybe, INotifyCompletion { private IMaybe _parent; void IMaybe.SetParent(IMaybe parent) => this._parent = parent; ... } public class MaybeTaskMethodBuilder<T> { ... private void GenericAwaitOnCompleted<TAwaiter, TStateMachine>( ref TAwaiter awaiter, ref TStateMachine stateMachine) where TAwaiter : INotifyCompletion where TStateMachine : IAsyncStateMachine { if (awaiter is IMaybe maybe) { maybe.SetParent(this.Task); } awaiter.OnCompleted(stateMachine.MoveNext); } ... }
рдЕрдм рд╕рднреА рд╣реЛ рд╕рдХрддрд╛ рд╣реИ рдХрд┐ рд╡рд╕реНрддреБрдУрдВ рдХреЛ рдПрдХ рдкреЗрдбрд╝ рдореЗрдВ рдЬреЛрдбрд╝рд╛ рдЬрд╛ рд╕рдХреЗ рдФрд░, рдкрд░рд┐рдгрд╛рдорд╕реНрд╡рд░реВрдк, рд╣рдо рдХрд┐рд╕реА рднреА рд╡рдВрд╢рдЬ рдиреЛрдб рд╕реЗ рд░реВрдЯ рдХреА рдирд┐рд░рдВрддрд░рддрд╛ ( рдПрдХреНрдЬрд┐рдЯ рд╡рд┐рдзрд┐) рддрдХ рдкрд╣реБрдВрдЪ рдкрд╛рдПрдВрдЧреЗ:
[AsyncMethodBuilder(typeof(MaybeTaskMethodBuilder<>))] public class Maybe<T> : IMaybe, INotifyCompletion { private Action _continuation; private IMaybe _parent; ... public void OnCompleted(Action continuation) { ... this._continuation = continuation; ... } ... void IMaybe.Exit() { this.IsCompleted = true; if (this._parent != null) { this._parent.Exit(); } else { this._continuation(); } } ... }
рдЙрд╕ рдирд┐рдХрд╛рд╕ рд╡рд┐рдзрд┐ рдХреЛ рддрдм рдмреБрд▓рд╛рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдП рдЬрдм (рдкреЗрдбрд╝ рдкрд░ рдЖрдЧреЗ рдмрдврд╝рдиреЗ рдХреЗ рджреМрд░рд╛рди) рд╣рдореЗрдВ рдХреБрдЫ рднреА рдирд╣реАрдВ рд░рд╛рдЬреНрдп рдореЗрдВ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рд╣рд▓ рдХреА рдЧрдИ рд╡рд╕реНрддреБ рдорд┐рд▓ рдЬрд╛рдПред рдЗрд╕ рддрд░рд╣ рдХреА рд╡рд╕реНрддреБрдУрдВ рдХреЛ рдЗрд╕ рддрд░рд╣ рд╕реЗ рдПрдХ рд╡рд┐рдзрд┐ рджреНрд╡рд╛рд░рд╛ рд╡рд╛рдкрд╕ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ:
Maybe<int> Parse(string str) => int.TryParse(str, out var result) ? result : Maybe<int>.Nothing();
рд╕реБрд▓рдЭреА рд╣реБрдИ рдЕрд╡рд╕реНрдерд╛ рдХреЛ рд╕рдВрдЪрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╢рд╛рдпрдж рдПрдХ рдЕрд▓рдЧ рд╕рдВрд░рдЪрдирд╛ рдкреНрд░рд╕реНрддреБрдд рдХрд░реЗрдВ:
public struct MaybeResult { ... private readonly T _value; public readonly bool IsNothing; public T GetValue() => this.IsNothing ? throw new Exception("Nothing") : this._value; } [AsyncMethodBuilder(typeof(MaybeTaskMethodBuilder<>))] public class Maybe<T> : IMaybe, INotifyCompletion { private MaybeResult? _result; ... internal Maybe() { }
рдЬрдм рдХреЛрдИ рдПрд╕реНрдХрд┐рдВрдЯ рд╕реНрдЯреЗрдЯ рдорд╢реАрди рдХреЙрд▓ рдХрд░рддреА рд╣реИ (рдореЗрдердб рдмрд┐рд▓реНрдбрд░ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ) рддреЛ рдСрди-рд▓рд╛рдИрдХ рд╡рд┐рдзрд┐ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рд╣рд▓ рд╣реЛ рд╕рдХрддреА рд╣реИ рд╢рд╛рдпрдж рдЙрджрд╛рд╣рд░рдг рдФрд░ рдпрд╣ рдХреБрдЫ рднреА рдирд╣реАрдВ рд╣реИ рд░рд╛рдЬреНрдп рдореЗрдВ рд╣рдо рдПрдХ рд╕рдВрдкреВрд░реНрдг рдкреНрд░рд╡рд╛рд╣ рдХреЛ рддреЛрдбрд╝рдиреЗ рдореЗрдВ рд╕рдХреНрд╖рдо рд╣реЛрдВрдЧреЗ:
public void OnCompleted(Action continuation) { this._continuation = continuation; if(this._result.HasValue) { this.NotifyResult(this._result.Value.IsNothing); } } internal void SetResult(T result)
рдЕрдм рдХреЗрд╡рд▓ рдПрдХ рдЪреАрдЬ рдмрдЪреА рд╣реБрдИ рд╣реИ - рдПрдХ async рдХрд╛ рдкрд░рд┐рдгрд╛рдо рдХреИрд╕реЗ рдкреНрд░рд╛рдкреНрдд рдХрд░реЗрдВ рд╢рд╛рдпрдж рдЗрд╕рдХреЗ рджрд╛рдпрд░реЗ рд╕реЗ рдмрд╛рд╣рд░ (рдХреЛрдИ async рд╡рд┐рдзрд┐ рдЬрд┐рд╕рдХрд╛ рд╡рд╛рдкрд╕реА рдкреНрд░рдХрд╛рд░ рд╢рд╛рдпрдж рдирд╣реАрдВ рд╣реИ)ред рдпрджрд┐ рдЖрдк рд╢рд╛рдпрдж рдПрдХ рдЙрджрд╛рд╣рд░рдг рдХреЗ рд╕рд╛рде рдкреНрд░рддреАрдХреНрд╖рд╛ рдХрд░рдиреЗ рд╡рд╛рд▓реЗ рдХреАрд╡рд░реНрдб рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд░рддреЗ рд╣реИрдВ рддреЛ рдЗрд╕ рдХреЛрдб рдХреЗ рдХрд╛рд░рдг рдПрдХ рдЕрдкрд╡рд╛рдж рдлреЗрдВрдХ рджрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛:
[AsyncMethodBuilder(typeof(MaybeTaskMethodBuilder<>))] public class Maybe<T> : IMaybe, INotifyCompletion { private MaybeResult? _result; public T GetResult() => this._result.Value.GetValue(); } ... public struct MaybeResult { ... public T GetValue() => this.IsNothing ? throw new Exception("Nothing") : this._value; }
рдЗрд╕ рд╕рдорд╕реНрдпрд╛ рдХреЛ рд╣рд▓ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╣рдо рдмрд╕ рдПрдХ рдирдпрд╛ рдПрд╡рд╛рдЯрд░ рдЬреЛрдбрд╝ рд╕рдХрддреЗ рд╣реИрдВ, рдЬреЛ рдХрд┐ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рд╣реЛ рд╕рдХрддрд╛ рд╣реИред рдореВрд▓ рд╕рдВрд░рдЪрдирд╛ рдФрд░ рд╣рдо рдЗрд╕ рдкрд░ рдПрдХ рдХреЛрдб рд▓рд┐рдЦрдиреЗ рдореЗрдВ рд╕рдХреНрд╖рдо рд╣реЛрдВрдЧреЗ:
var res = await GetResult().GetMaybeResult(); if(res.IsNothing){ ... } else{ res.GetValue(); ... };
рдЕрднреА рдХреЗ рд▓рд┐рдП рдмрд╕ рдЗрддрдирд╛ рд╣реАред рдХреЛрдб рдХреЗ рдирдореВрдиреЛрдВ рдореЗрдВ рдореИрдВ рдХреЗрд╡рд▓ рд╕рдмрд╕реЗ рдорд╣рддреНрд╡рдкреВрд░реНрдг рднрд╛рдЧреЛрдВ рдкрд░ рдзреНрдпрд╛рди рдХреЗрдВрджреНрд░рд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХреБрдЫ рд╡рд┐рд╡рд░рдгреЛрдВ рдХреЛ рдЫреЛрдбрд╝ рджреЗрддрд╛ рд╣реВрдВред рдЖрдк рдЬреАрдердм рдкрд░ рдПрдХ рдкреВрд░реНрдг рд╕рдВрд╕реНрдХрд░рдг рдкрд╛ рд╕рдХрддреЗ рд╣реИрдВред
рд╣рд╛рд▓рд╛рдБрдХрд┐ , рдореИрдВ рдЗрд╕ рд╕рдВрд╕реНрдХрд░рдг рдХреЛ рдХрд┐рд╕реА рднреА рдЙрддреНрдкрд╛рджрди рдХреЛрдб рдореЗрдВ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреА рд╕рд┐рдлрд╛рд░рд┐рд╢ рдирд╣реАрдВ рдХрд░реВрдВрдЧрд╛ рдХреНрдпреЛрдВрдХрд┐ рдЗрд╕рдореЗрдВ рдПрдХ рдорд╣рддреНрд╡рдкреВрд░реНрдг рдореБрджреНрджрд╛ рд╣реИ - рдЬрдм рд╣рдо рд░реВрдЯ рдХреЗ рдПрдХ рдирд┐рд░рдВрддрд░рддрд╛ рдХреЛ рдХреЙрд▓ рдХрд░рдХреЗ рдПрдХ рдирд┐рд╖реНрдкрд╛рджрди рдкреНрд░рд╡рд╛рд╣ рдХреЛ рддреЛрдбрд╝ рджреЗрдВрдЧреЗ рддреЛ рд╢рд╛рдпрдж рд╣рдо рд╕рдмрдХреЛ рдмрд╛рдпрдкрд╛рд╕ рдХрд░ рджреЗрдВрдЧреЗ! рд╕рднреА рдЕрдВрдд рдореЗрдВ рдмреНрд▓реЙрдХ рд╕рд╣рд┐рдд (рдпрд╣ рд╕рд╡рд╛рд▓ рдХрд╛ рдПрдХ рдЙрддреНрддрд░ рд╣реИ " рдЖрдЦрд┐рд░рдХрд╛рд░ рдмреНрд▓реЙрдХ рд╣рдореЗрд╢рд╛ рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИ?"), рдЗрд╕рд▓рд┐рдП рд╕рднреА рдСрдкрд░реЗрдЯрд░реЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдЙрдореНрдореАрдж рдХреЗ рдореБрддрд╛рдмрд┐рдХ рдХрд╛рдо рдирд╣реАрдВ рдХрд░реЗрдЧрд╛ рдФрд░ рдЗрд╕рд╕реЗ рд╕рдВрд╕рд╛рдзрди рд▓реАрдХ рд╣реЛ рд╕рдХрддрд╛ рд╣реИред рд╕рдорд╕реНрдпрд╛ рдХреЛ рд╣рд▓ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ рдпрджрд┐ рдкреНрд░рд╛рд░рдВрднрд┐рдХ рдирд┐рд░рдВрддрд░рддрд╛ рдХреЙрд▓рдмреИрдХ рдХреЛ рдХреЙрд▓ рдХрд░рдиреЗ рдХреЗ рдмрдЬрд╛рдп рд╣рдо рдПрдХ рд╡рд┐рд╢реЗрд╖ рдЕрдкрд╡рд╛рдж рдХреЛ рдлреЗрдВрдХ рджреЗрдВрдЧреЗ рдЬрд┐рд╕реЗ рдЖрдВрддрд░рд┐рдХ рд░реВрдк рд╕реЗ рдирд┐рдпрдВрддреНрд░рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ ( рдпрд╣рд╛рдВ рдЖрдк рд╕рдВрд╕реНрдХрд░рдг рдкрд╛ рд╕рдХрддреЗ рд╣реИрдВ ), рд▓реЗрдХрд┐рди рдЗрд╕ рд╕рдорд╛рдзрд╛рди рдореЗрдВ рд╕реНрдкрд╖реНрдЯ рд░реВрдк рд╕реЗ рдкреНрд░рджрд░реНрд╢рди рдирдХрд▓реЗрдВ рд╣реИрдВ (рдЬреЛ рдХреБрдЫ рдкрд░рд┐рджреГрд╢реНрдпреЛрдВ рдореЗрдВ рд╕реНрд╡реАрдХрд╛рд░реНрдп рд╣реЛ рд╕рдХрддреА рд╣реИрдВ)ред C # рд╕рдВрдХрд▓рдХ рдХреЗ рд╡рд░реНрддрдорд╛рди рд╕рдВрд╕реНрдХрд░рдг рдХреЗ рд╕рд╛рде рдореБрдЭреЗ рдХреЛрдИ рдЕрдиреНрдп рд╕рдорд╛рдзрд╛рди рдирд╣реАрдВ рджрд┐рдЦрддрд╛ рд╣реИ рд▓реЗрдХрд┐рди рднрд╡рд┐рд╖реНрдп рдореЗрдВ рдЗрд╕реЗ рдмрджрд▓рд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред
рдЗрди рд╕реАрдорд╛рдУрдВ рдХрд╛ рдорддрд▓рдм рдпрд╣ рдирд╣реАрдВ рд╣реИ рдХрд┐ рдЗрд╕ рд▓реЗрдЦ рдореЗрдВ рд╡рд░реНрдгрд┐рдд рд╕рднреА рддрд░рдХреАрдмреЗрдВ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рдмреЗрдХрд╛рд░ рд╣реИрдВ, рдЙрдирдХрд╛ рдЙрдкрдпреЛрдЧ рдЕрдиреНрдп рд╕рд╛рдзреБрдУрдВ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ рдЬрд┐рдиреНрд╣реЗрдВ рдирд┐рд╖реНрдкрд╛рджрди рдкреНрд░рд╡рд╛рд╣ рдореЗрдВ рдмрджрд▓рд╛рд╡ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ рд╣реИ, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП "рд░реАрдбрд░"ред рдЙрд╕ "рд░реАрдбрд░" рдХреЛ рдХреИрд╕реЗ рд▓рд╛рдЧреВ рдХрд┐рдпрд╛ рдЬрд╛рдП?