Skip to content

Instantly share code, notes, and snippets.

@nenoNaninu
Created June 6, 2020 17:35
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 nenoNaninu/53d1e7590270f803e397f46ba291e2d5 to your computer and use it in GitHub Desktop.
Save nenoNaninu/53d1e7590270f803e397f46ba291e2d5 to your computer and use it in GitHub Desktop.
C# awaitおもしろコード
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