Last active
February 6, 2018 06:46
-
-
Save geoder101/9248156 to your computer and use it in GitHub Desktop.
TPL C# extension methods
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
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