Skip to content

Instantly share code, notes, and snippets.

@geoder101
Last active February 6, 2018 06:46
Show Gist options
  • Save geoder101/9248156 to your computer and use it in GitHub Desktop.
Save geoder101/9248156 to your computer and use it in GitHub Desktop.
TPL C# extension methods
namespace Extensions
{
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
/// <summary>
/// LINQ extension methods for the TPL-'Task' monad.
/// </summary>
/// <remarks>
/// A C# 4.0 implementation of http://blogs.msdn.com/b/pfxteam/archive/2013/04/03/tasks-monads-and-linq.aspx
/// </remarks>
public static class TaskLinqExtensions
{
public static Task<T> TaskUnit<T>(this T value)
{
return Task.Factory.StartNew(() => value);
}
public static Task<V> TaskBind<U, V>(
this Task<U> m, Func<U, Task<V>> k)
{
return m.ContinueWith(m_ => k(m_.Result)).Unwrap();
}
public static Task<C> SelectMany<A, B, C>(
this Task<A> monad,
Func<A, Task<B>> function,
Func<A, B, C> projection)
{
return monad.TaskBind(
outer => function(outer).TaskBind(
inner => projection(outer, inner).TaskUnit()));
}
public static Task<U> Select<T, U>(
this Task<T> source, Func<T, U> selector)
{
return source.TaskBind(t => selector(t).TaskUnit());
}
public static Task<T> Where<T>(
this Task<T> source, Func<T, bool> predicate)
{
return source.TaskBind(t =>
{
if (!predicate(t))
throw new OperationCanceledException();
return t.TaskUnit();
}
);
}
public static Task<V> Join<T, U, K, V>(
this Task<T> source, Task<U> inner,
Func<T, K> outerKeySelector, Func<U, K> innerKeySelector,
Func<T, U, V> resultSelector)
{
Task.WaitAll(new Task[] { source, inner });
return source.TaskBind(t =>
{
return inner.TaskBind(u =>
{
if (!EqualityComparer<K>.Default.Equals(outerKeySelector(t), innerKeySelector(u)))
throw new OperationCanceledException();
return resultSelector(t, u).TaskUnit();
}
);
}
);
}
public static Task<V> GroupJoin<T, U, K, V>(
this Task<T> source, Task<U> inner,
Func<T, K> outerKeySelector, Func<U, K> innerKeySelector,
Func<T, Task<U>, V> resultSelector)
{
return source.TaskBind(t =>
{
return resultSelector(
t,
inner.Where(u =>
EqualityComparer<K>.Default.Equals(
outerKeySelector(t),
innerKeySelector(u)
)
)
).TaskUnit();
}
);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment