Created
June 6, 2020 17:35
-
-
Save nenoNaninu/53d1e7590270f803e397f46ba291e2d5 to your computer and use it in GitHub Desktop.
C# awaitおもしろコード
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
using System; | |
using System.Collections.Generic; | |
using System.Runtime.CompilerServices; | |
namespace ConsoleApp2 | |
{ | |
public static class EnumerableEx | |
{ | |
public static IEnumerable<T> Create<T>(Action<IYielder<T>> create) | |
{ | |
if (create == null) throw new ArgumentNullException("create"); | |
foreach (var x in new Yielder<T>(create)) | |
{ | |
yield return x; | |
} | |
} | |
} | |
public interface IYielder<in T> | |
{ | |
IAwaitable Return(T value); | |
IAwaitable Break(); | |
} | |
public interface IAwaitable | |
{ | |
IAwaiter GetAwaiter(); | |
} | |
public interface IAwaiter : ICriticalNotifyCompletion | |
{ | |
bool IsCompleted { get; } | |
void GetResult(); | |
} | |
public class Yielder<T> : IYielder<T>, IAwaitable, IAwaiter, ICriticalNotifyCompletion | |
{ | |
private readonly Action<Yielder<T>> _create; | |
private bool _running; | |
private bool _hasValue; | |
private T _value; | |
private bool _stopped; | |
private Action _continuation; | |
public Yielder(Action<Yielder<T>> create) | |
{ | |
_create = create; | |
} | |
public IAwaitable Return(T value) | |
{ | |
_hasValue = true; | |
_value = value; | |
return this; | |
} | |
public IAwaitable Break() | |
{ | |
_stopped = true; | |
return this; | |
} | |
public Yielder<T> GetEnumerator() | |
{ | |
return this; | |
} | |
public bool MoveNext() | |
{ | |
if (!_running) | |
{ | |
_running = true; | |
_create(this); | |
} | |
else | |
{ | |
_hasValue = false; | |
_continuation(); | |
} | |
return !_stopped && _hasValue; | |
} | |
public T Current | |
{ | |
get | |
{ | |
return _value; | |
} | |
} | |
public IAwaiter GetAwaiter() | |
{ | |
return this; | |
} | |
public bool IsCompleted | |
{ | |
get { return false; } | |
} | |
public void GetResult() { } | |
public void OnCompleted(Action continuation) | |
{ | |
_continuation = continuation; | |
} | |
public void UnsafeOnCompleted(Action continuation) | |
{ | |
_continuation = continuation; | |
} | |
} | |
class Program | |
{ | |
static void Main(string[] args) | |
{ | |
var hoge = "あいうえお"; | |
var seq = EnumerableEx.Create<int>(async Yield => | |
{ | |
await Yield.Return(10); | |
await Yield.Return(100); | |
hoge = "ふがふが"; // インラインで書けるのでお外への副作用が可能 | |
await Yield.Return(1000); | |
}); | |
foreach (var item in seq) | |
{ | |
Console.WriteLine(item); // 10, 100, 1000 | |
} | |
Console.WriteLine(hoge); // ふがふが | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment