Skip to content

Instantly share code, notes, and snippets.

@Thecentury
Created January 8, 2014 16:52
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 Thecentury/8320051 to your computer and use it in GitHub Desktop.
Save Thecentury/8320051 to your computer and use it in GitHub Desktop.
using System;
using System.Threading.Tasks;
namespace SelectMany
{
public static class SelectManyExtensions
{
public static Func<TResult> SelectMany<T1, T2, TResult>( this Func<T1> f1, Func<T1, Func<T2>> selector,
Func<T1, T2, TResult> resultSelector )
{
return () =>
{
var v1 = f1();
var f2 = selector( v1 );
var v2 = f2();
return resultSelector( v1, v2 );
};
}
public static async Task<TResult> SelectMany<T1, T2, TResult>( this Task<T1> t1, Func<T1, Task<T2>> selector,
Func<T1, T2, TResult> resultSelector )
{
var v1 = await t1;
var t2 = selector( v1 );
var v2 = await t2;
return resultSelector( v1, v2 );
}
public static TResult? SelectMany<T1, T2, TResult>( this T1? n1, Func<T1, T2?> selector,
Func<T1, T2, TResult> resultSelector )
where T1 : struct
where T2 : struct
where TResult : struct
{
if ( n1 == null )
{
return null;
}
var v1 = n1.Value;
var n2 = selector( v1 );
if ( n2 == null )
{
return null;
}
var result = resultSelector( v1, n2.Value );
return result;
}
public static Lazy<TResult> SelectMany<T1, T2, TResult>( this Lazy<T1> l1, Func<T1, Lazy<T2>> selector,
Func<T1, T2, TResult> resultSelector )
{
return new Lazy<TResult>( () =>
{
var v1 = l1.Value;
var l2 = selector( v1 );
return resultSelector( v1, l2.Value );
} );
}
}
public class Tests
{
public Func<int> F1 = () => 1;
public Func<int> F2 = () => 2;
public void Func()
{
var z = from x in F1
from y in F2
select x + y;
}
public void Tasks()
{
var z = from x in Task.FromResult( 1 )
from y in Task.FromResult( 2 )
select x + y;
}
public int? N1 = 1;
public int? N2 = 2;
public void Nullables()
{
var z = from x in N1
from y in N2
select x + y;
}
public Lazy<int> L1 = new Lazy<int>( () => 1 );
public Lazy<int> L2 = new Lazy<int>( () => 2 );
public void Lazies()
{
var z = from x in L1
from y in L2
select x + y;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment