Implementing the Choice Type in C# - c#

for educational reasons I'm trying to implement the Choice and the Option Type from F# in C#. This was inspired by the book "Real World Functional Programming" and some blog posts like: http://bugsquash.blogspot.de/2011/08/refactoring-to-monadic-c-applicative.html and http://tomasp.net/blog/idioms-in-linq.aspx/.
I would like to get this to work, but I don't know how to implement the Extensions for the Choice Type (Bind, Map, SelectMany, ...):
public static void Division()
{
Console.WriteLine("Enter two (floating point) numbers:");
(
from f1 in ReadDouble().ToChoice("Could not parse input to a double.")
from f2 in ReadDouble().ToChoice("Could not parse input to a double.")
from result in Divide(f1, f2).ToChoice("Cannot divide by zero.")
select result
)
.Match(
x => Console.WriteLine("Result = {0}", x),
x => Console.WriteLine("Error: {0}", x));
}
public static Option<double> Divide(double a, double b)
{
return b == 0 ? Option.None<double>() : Option.Some(a / b);
}
public static Option<Double> ReadDouble()
{
double i;
if (Double.TryParse(Console.ReadLine(), out i))
return Option.Some(i);
else
return Option.None<double>();
}
public static Option<int> ReadInt()
{
int i;
if (Int32.TryParse(Console.ReadLine(), out i))
return Option.Some(i);
else
return Option.None<int>();
}
}
The Option Type looks like this:
public enum OptionType
{
Some, None
}
public abstract class Option<T>
{
private readonly OptionType _tag;
protected Option(OptionType tag)
{
_tag = tag;
}
public OptionType Tag { get { return _tag; } }
internal bool MatchNone()
{
return Tag == OptionType.None;
}
internal bool MatchSome(out T value)
{
value = Tag == OptionType.Some ? ((Some<T>)this).Value : default(T);
return Tag == OptionType.Some;
}
public void Match(Action<T> onSome, Action onNone)
{
if (Tag == OptionType.Some)
onSome(((Some<T>)this).Value);
else
onNone();
}
public Choice<T, T2> ToChoice<T2>(T2 value)
{
if (Tag == OptionType.Some)
{
T some;
MatchSome(out some);
return Choice.NewChoice1Of2<T, T2>(some);
}
else
return Choice.NewChoice2Of2<T, T2>(value);
}
}
internal class None<T> : Option<T>
{
public None() : base(OptionType.None) { }
}
internal class Some<T> : Option<T>
{
public Some(T value)
: base(OptionType.Some)
{
_value = value;
}
private readonly T _value;
public T Value { get { return _value; } }
}
public static class Option
{
public static Option<T> None<T>()
{
return new None<T>();
}
public static Option<T> Some<T>(T value)
{
return new Some<T>(value);
}
}
public static class OptionExtensions
{
public static Option<TResult> Map<T, TResult>(this Option<T> source, Func<T, TResult> selector)
{
T value;
return source.MatchSome(out value) ? Option.Some(selector(value)) : Option.None<TResult>();
}
public static Option<TResult> Bind<T, TResult>(this Option<T> source, Func<T, Option<TResult>> selector)
{
T value;
return source.MatchSome(out value) ? selector(value) : Option.None<TResult>();
}
public static Option<TResult> Select<T, TResult>(this Option<T> source, Func<T, TResult> selector)
{
return source.Map(selector);
}
public static Option<TResult> SelectMany<TSource, TValue, TResult>(this Option<TSource> source, Func<TSource, Option<TValue>> valueSelector, Func<TSource, TValue, TResult> resultSelector)
{
return source.Bind(s => valueSelector(s).Map(v => resultSelector(s, v)));
}
}
And here is the Choice Type Implementation:
public enum ChoiceType { Choice1Of2, Choice2Of2 };
public abstract class Choice<T1, T2>
{
private readonly ChoiceType _tag;
protected Choice(ChoiceType tag)
{
_tag = tag;
}
public ChoiceType Tag { get { return _tag; } }
internal bool MatchChoice1Of2(out T1 value)
{
value = Tag == ChoiceType.Choice1Of2 ? ((Choice1Of2<T1, T2>)this).Value : default(T1);
return Tag == ChoiceType.Choice1Of2;
}
internal bool MatchChoice2Of2(out T2 value)
{
value = Tag == ChoiceType.Choice2Of2 ? ((Choice2Of2<T1, T2>)this).Value : default(T2);
return Tag == ChoiceType.Choice2Of2;
}
public void Match(Action<T1> onChoice1Of2, Action<T2> onChoice2Of2)
{
if (Tag == ChoiceType.Choice1Of2)
onChoice1Of2(((Choice1Of2<T1, T2>)this).Value);
else
onChoice2Of2(((Choice2Of2<T1, T2>)this).Value);
}
}
internal class Choice1Of2<T1, T2> : Choice<T1, T2>
{
public Choice1Of2(T1 value)
: base(ChoiceType.Choice1Of2)
{
_value = value;
}
private readonly T1 _value;
public T1 Value { get { return _value; } }
}
internal class Choice2Of2<T1, T2> : Choice<T1, T2>
{
public Choice2Of2(T2 value)
: base(ChoiceType.Choice2Of2)
{
_value = value;
}
private readonly T2 _value;
public T2 Value { get { return _value; } }
}
public static class Choice
{
public static Choice<T1, T2> NewChoice1Of2<T1, T2>(T1 value)
{
return new Choice1Of2<T1, T2>(value);
}
public static Choice<T1, T2> NewChoice2Of2<T1, T2>(T2 value)
{
return new Choice2Of2<T1, T2>(value);
}
}
EDIT:
It actually works with the Extensions below. What I don't really like about it is that this implementation adds a context specific behaviour to the Choice type. This is because the Choice1Of2 is the prefered choice because all the extension methods mainly operate on it rather than on Choice2Of2 or both. (But that's what the consuming code actually implies, so I guess it is the only way to get it working.)
public static Choice<TResult, T2> Map<T1, T2, TResult>(this Choice<T1, T2> source, Func<T1, TResult> selector)
{
T1 value1;
if(source.MatchChoice1Of2(out value1))
{
return Choice.NewChoice1Of2<TResult, T2>(selector(value1));
}
T2 value2;
if (source.MatchChoice2Of2(out value2))
{
return Choice.NewChoice2Of2<TResult, T2>(value2);
}
throw new InvalidOperationException("source (:Choice) has no value.");
}
public static Choice<TResult, T2> Bind<T1, T2, TResult>(this Choice<T1, T2> source, Func<T1, Choice<TResult, T2>> selector)
{
T1 value1;
if (source.MatchChoice1Of2(out value1))
{
return selector(value1);
}
T2 value2;
if (source.MatchChoice2Of2(out value2))
{
return Choice.NewChoice2Of2<TResult, T2>(value2);
}
throw new InvalidOperationException("source (:Choice) has no value.");
}
public static Choice<TResult, T2> Select<T1, T2, TResult>(this Choice<T1, T2> source, Func<T1, TResult> selector)
{
return source.Map(selector);
}
public static Choice<TResult, T2> SelectMany<TSource, TValue, T2, TResult>(this Choice<TSource, T2> source, Func<TSource, Choice<TValue, T2>> valueSelector, Func<TSource, TValue, TResult> resultSelector)
{
return source.Bind(s => valueSelector(s).Map(v => resultSelector(s, v)));
}

Since Choice has two type parameters, you need to fix the first one to be able to write Select and SelectMany (bind):
public abstract class Choice<T1, T2>
{
public abstract Choice<T1, T3> Select<T3>(Func<T2, T3> f);
public abstract Choice<T1, T3> SelectMany<T3>(Func<T2, Choice<T1, T3>> f);
}
their implementation is straightforward for Choice1Of2:
public override Choice<T1, T3> Select<T3>(Func<T2, T3> f)
{
return new Choice1Of2<T1, T3>(this._value);
}
public override Choice<T1, T3> SelectMany<T3>(Func<T2, Choice<T1, T3>> f)
{
return new Choice1Of2<T1, T3>(this._value);
}
and for Choice2Of2 you just need to provide the inner value to the given function:
public override Choice<T1, T3> Select<T3>(Func<T2, T3> f)
{
return new Choice2Of2<T1, T3>(f(this.Value));
}
public override Choice<T1, T3> SelectMany<T3>(Func<T2, Choice<T1, T3>> f)
{
return f(this._value);
}
You may also want a BiSelect function for mapping over both type parameters:
public abstract BiSelect<T3, T4>(Func<T1, T3> ff, Func<T2, T4> fs);
If you want to use SelectMany with the linq query syntax, you need to implement another overload which looks like:
public abstract Choice<T1, T4> SelectMany<T3, T4>(Func<T2, Choice<T1, T3>> f, Func<T2, T3, T4> selector);
The implementation for Choice1Of2 is similar to before:
public override Choice<T1, T4> SelectMany<T3, T4>(Func<T2, Choice<T1, T3>> f, Func<T2, T3, T4> selector)
{
return new Choice1Of2<T1, T4>(this._value);
}
The implementation for Choice2Of2 is then:
public override Choice<T1, T4> SelectMany<T3, T4>(Func<T2, Choice<T1, T3>> f, Func<T2, T3, T4> selector)
{
T2 val = this._value;
var e = f(val);
return e.Select(v => selector(val, v));
}
and you can do:
var choice = from x in new Choice2Of2<string, int>(1)
from y in new Choice2Of2<string, int>(4)
select x + y;

Here is one new extensions class to make 'Match' method works on IEnumerable
public static class ChoiceExtensions
{
// You need this method, because code 'select result' is a LINQ expression and it returns IEnumerable
public static void Match<T1, T2>(this IEnumerable<Choice<T1, T2>> seq, Action<T1> onChoice1Of2, Action<T2> onChoice2Of2)
{
foreach (var choice in seq)
{
choice.Match(onChoice1Of2, onChoice2Of2);
}
}
// This method will help with the complex matching
public static Choice<T1, T2> Flat<T1, T2>(this Choice<Choice<T1, T2>, T2> choice)
{
Choice<T1, T2> result = null;
choice.Match(
t1 => result = t1,
t2 => result = new Choice2Of2<T1, T2>(t2));
return result;
}
}
Also, I've changed your Choice class:
// Implement IEnumerable to deal with LINQ
public abstract class Choice<T1, T2> : IEnumerable<Choice<T1, T2>>
{
IEnumerator<Choice<T1, T2>> IEnumerable<Choice<T1, T2>>.GetEnumerator()
{
yield return this;
}
public IEnumerator GetEnumerator()
{
yield return this;
}
// These two methods work with your Devide function
// I think, it is good to throw an exception here, if c is not a choice of 1
public static implicit operator T1(Choice<T1, T2> c)
{
T1 val;
c.MatchChoice1Of2(out val);
return val;
}
// And you can add exception here too
public static implicit operator T2(Choice<T1, T2> c)
{
T2 val;
c.MatchChoice2Of2(out val);
return val;
}
// Your Match method returns void, it is not good in functional programming,
// because, whole purpose of the method returning void is the change state,
// and in FP state is immutable
// That's why I've created PureMatch method for you
public Choice<T1Out, T2Out> PureMatch<T1Out, T2Out>(Func<T1, T1Out> onChoice1Of2, Func<T2, T2Out> onChoice2Of2)
{
Choice<T1Out, T2Out> result = null;
Match(
t1 => result = new Choice1Of2<T1Out, T2Out>(onChoice1Of2(t1)),
t2 => result = new Choice2Of2<T1Out, T2Out>(onChoice2Of2(t2)));
return result;
}
// Continue Choice class
}
Your sample is slightly incorrect, because when you write:
from f1 in ReadDouble().ToChoice("Could not parse input to a double.")
from f2 in ReadDouble().ToChoice("Could not parse input to a double.")
from result in Devide(f1, f2).ToChoice("Cannot devide by zero.")
select result
in the last line you actually ignore f1 and f2. So it is impossible to see parsing error. Better write:
(
from f1 in ReadDouble().ToChoice("Could not parse input to a double.")
from f2 in ReadDouble().ToChoice("Could not parse input to a double.")
from result in
f1.PureMatch(
f1value => f2.PureMatch(
f2value => Devide(f1, f2).ToChoice("Cannot devide by zero."),
f2err => f2err).Flat(),
f1err => f1err
).Flat()
select result
)
.Match(
x => Console.WriteLine("Result = {0}", x),
x => Console.WriteLine("Error: {0}", x));
You can create nice helper methods to deal with this complicated stuff, something like PureMatch method but with more arguments

Related

Func<> with unknown number of parameters

Consider the following pseudo code:
TResult Foo<TResult>(Func<T1, T2,...,Tn, TResult> f, params object[] args)
{
TResult result = f(args);
return result;
}
The function accepts Func<> with unknown number of generic parameters and a list of the corresponding arguments. Is it possible to write it in C#? How to define and call Foo? How do I pass args to f?
You can use Delegate with DynamicInvoke.
With that, you don't need to handle with object[] in f.
TResult Foo<TResult>(Delegate f, params object[] args)
{
var result = f.DynamicInvoke(args);
return (TResult)Convert.ChangeType(result, typeof(TResult));
}
Usage:
Func<string, int, bool, bool> f = (name, age, active) =>
{
if (name == "Jon" && age == 40 && active)
{
return true;
}
return false;
};
Foo<bool>(f,"Jon", 40, true);
I created a fiddle showing some examples: https://dotnetfiddle.net/LdmOqo
Note:
If you want to use a method group, you need to use an explict casting to Func:
public static bool Method(string name, int age)
{
...
}
var method = (Func<string, int, bool>)Method;
Foo<bool>(method, "Jon", 40);
Fiddle: https://dotnetfiddle.net/3ZPLsY
That's not possible. At best, you could have a delegate that also takes a variable number of arguments, and then have the delegate parse the arguments
TResult Foo<TResult>(Func<object[], TResult> f, params object[] args)
{
TResult result = f(args);
return result;
}
Foo<int>(args =>
{
var name = args[0] as string;
var age = (int) args[1];
//...
return age;
}, arg1, arg2, arg3);
This could become easy with lambda expressions:
TResult Foo<TResult>(Func<TResult> f)
{
return f();
}
Then usage could be like:
var result = Foo<int>(() => method(arg1, arg2, arg3));
Where method can be arbitrary method returning int.
This way you can pass any number of any erguments directly through lambda.
To support asynchoronous code we can define:
Task<TResult> Foo<TResult>(Func<Task<TResult>> f)
{
return f();
}
// or with cancellation token
Task<TResult> Foo<TResult>(Func<CancellationToken, Task<TResult>> f, CancellationToken cancellationToken)
{
return f(cancellationToken);
}
and use it like:
var asyncResult = await Foo(async () => await asyncMethod(arg1, arg2, arg3));
// With cancellation token
var asyncResult = await Foo(
async (ct) => await asyncMethod(arg1, arg2, arg3, ct),
cancellationToken);
You could try something similar to what I posted here: https://stackoverflow.com/a/47556051/4681344
It will allow for any number of arguments, and enforces their types.
public delegate T ParamsAction<T>(params object[] args);
TResult Foo<TResult>(ParamsAction<TResult> f)
{
TResult result = f();
return result;
}
to call it, simply......
Foo(args => MethodToCallback("Bar", 123));
In some cases you may be able to get away with a trick like this:
public static class MyClass
{
private static T CommonWorkMethod<T>(Func<T> wishMultipleArgsFunc)
{
// ... do common preparation
T returnValue = wishMultipleArgsFunc();
// ... do common cleanup
return returnValue;
}
public static int DoCommonWorkNoParams() => CommonWorkMethod<int>(ProduceIntWithNoParams);
public static long DoCommonWorkWithLong(long p1) => CommonWorkMethod<long>(() => ProcessOneLong(p1));
public static string DoCommonWorkWith2Params(int p1, long p2) => CommonWorkMethod<string>(() => ConvertToCollatedString(p1, p2));
private static int ProduceIntWithNoParams() { return 5; }
}
Although it is not really what asked, a simple workaround would be to define several Foo method with different number of type arguments.
It is uncommon to have function with more than 6 parameters, so one could define the following method and get away with almost every use case, while staying type safe. Renan's solution could then be used for the remaining cases.
public TResult Foo<TResult> (Func<TResult> f)
{
return f();
}
public TResult Foo<T1, TResult>(Func<T1, TResult> f, T1 t1)
{
return f(t1);
}
public TResult Foo<T1, T2, TResult>(Func<T1, T2, TResult> f, T1 t1, T2 t2)
{
return f(t1, t2);
}
...

What is the equivalent of a Tuple in .NET 3.5? [duplicate]

Is there a class existing in .NET Framework 3.5 that would be equivalent to the .NET 4 Tuple?
I would like to use it in order to return several values from a method, rather than create a struct.
No, not in .Net 3.5. But it shouldn't be that hard to create your own.
public class Tuple<T1, T2>
{
public T1 First { get; private set; }
public T2 Second { get; private set; }
internal Tuple(T1 first, T2 second)
{
First = first;
Second = second;
}
}
public static class Tuple
{
public static Tuple<T1, T2> New<T1, T2>(T1 first, T2 second)
{
var tuple = new Tuple<T1, T2>(first, second);
return tuple;
}
}
UPDATE: Moved the static stuff to a static class to allow for type inference. With the update you can write stuff like var tuple = Tuple.New(5, "hello"); and it will fix the types for you implicitly.
I'm using this in my pre-4 projects:
public class Tuple<T1>
{
public Tuple(T1 item1)
{
Item1 = item1;
}
public T1 Item1 { get; set; }
}
public class Tuple<T1, T2> : Tuple<T1>
{
public Tuple(T1 item1, T2 item2) : base(item1)
{
Item2 = item2;
}
public T2 Item2 { get; set; }
}
public class Tuple<T1, T2, T3> : Tuple<T1, T2>
{
public Tuple(T1 item1, T2 item2, T3 item3) : base(item1, item2)
{
Item3 = item3;
}
public T3 Item3 { get; set; }
}
public static class Tuple
{
public static Tuple<T1> Create<T1>(T1 item1)
{
return new Tuple<T1>(item1);
}
public static Tuple<T1, T2> Create<T1, T2>(T1 item1, T2 item2)
{
return new Tuple<T1, T2>(item1, item2);
}
public static Tuple<T1, T2, T3> Create<T1, T2, T3>(T1 item1, T2 item2, T3 item3)
{
return new Tuple<T1, T2, T3>(item1, item2, item3);
}
}
In the event that you need them to have feature-parity with .Net 4.0 (primarily comparisson):
static class Tuple
{
public static Tuple<T1, T2> Create<T1, T2>(T1 item1, T2 item2)
{
return new Tuple<T1, T2>(item1, item2);
}
}
[DebuggerDisplay("Item1={Item1};Item2={Item2}")]
class Tuple<T1, T2> : IFormattable
{
public T1 Item1 { get; private set; }
public T2 Item2 { get; private set; }
public Tuple(T1 item1, T2 item2)
{
Item1 = item1;
Item2 = item2;
}
#region Optional - If you need to use in dictionaries or check equality
private static readonly IEqualityComparer<T1> Item1Comparer = EqualityComparer<T1>.Default;
private static readonly IEqualityComparer<T2> Item2Comparer = EqualityComparer<T2>.Default;
public override int GetHashCode()
{
var hc = 0;
if (!object.ReferenceEquals(Item1, null))
hc = Item1Comparer.GetHashCode(Item1);
if (!object.ReferenceEquals(Item2, null))
hc = (hc << 3) ^ Item2Comparer.GetHashCode(Item2);
return hc;
}
public override bool Equals(object obj)
{
var other = obj as Tuple<T1, T2>;
if (object.ReferenceEquals(other, null))
return false;
else
return Item1Comparer.Equals(Item1, other.Item1) && Item2Comparer.Equals(Item2, other.Item2);
}
#endregion
#region Optional - If you need to do string-based formatting
public override string ToString() { return ToString(null, CultureInfo.CurrentCulture); }
public string ToString(string format, IFormatProvider formatProvider)
{
return string.Format(formatProvider, format ?? "{0},{1}", Item1, Item2);
}
#endregion
}
You can install NetLegacySupport.Tuple via nuget. This is the Tuple class from .Net 4.5 backported to .Net 2.0 and 3.5.
You can install this via the package manager in Visual Studio or using nuget on the commandline.
Here is the nuget package:
https://www.nuget.org/packages/NetLegacySupport.Tuple
Yes, there is a class called System.Collections.Generic.KeyValuePair that does the same thing (since .NET 2.0 I think).
http://msdn.microsoft.com/en-us/library/5tbh8a42.aspx
Yes, you can just use Tuple.cs from mono:
You require the dependencies as well:
Tuples.cs
IStructuralComparable.cs
IStructuralEquatable.cs
You just put a
#define NET_4_0
in front of every
#if NET_4_0
and there you go, a feature-complete implementation of System.Tuple for .NET 2.0.

is it possible to convert Func<T1,T2,TResult> to Func<T2,T1,TResult>

First, foo is a Func<T1,T2,TResult> object.
Is is possible do something like
Func<T2,T1,TResult> bar = ConvertFunction(foo);
thus convert Func<T1,T2,TResult> to Func<T2,T1,TResult>.
Yes, that's possible:
Func<T2, T1, TResult> bar = (t2, t1) => foo(t1, t2);
That basically creates another delegate with switched parameters that internally simply calls the original delegate.
This is the only way to perform this kind of "conversion" if you only have a Func<T1, T2, TResult> and not a Expression<Func<T1, T2, TResult>>.
Here's the function:
class MyFuncConverter<T1, T2, TResult>
{
static Func<T1, T2, TResult> _foo;
public static Func<T2, T1, TResult> ConvertFunction(Func<T1, T2, TResult> foo)
{
_foo = foo;
return new Func<T2, T1, TResult>(MyFunc);
}
private static TResult MyFunc(T2 arg2, T1 arg1)
{
return _foo(arg1, arg2);
}
}
Sample usage:
static void Main(string[] args)
{
var arg1 = 10;
var arg2 = "abc";
// create a Func with parameters in reversed order
Func<string, int, string> testStringInt =
MyFuncConverter<int, string, string>.ConvertFunction(TestIntString);
var result1 = TestIntString(arg1, arg2);
var result2 = testStringInt(arg2, arg1);
// testing results
Console.WriteLine(result1 == result2);
}
/// <summary>
/// Sample method
/// </summary>
private static string TestIntString(int arg1, string arg2)
{
byte[] toEncodeAsBytes = System.Text.ASCIIEncoding.ASCII
.GetBytes(arg2.ToString() + arg1);
string returnValue = System.Convert.ToBase64String(toEncodeAsBytes);
return returnValue;
}

How does one tell if a LINQ extension method is suffering from double enumeration?

I am wondering what rules there are to tell if a portion of LINQ code is suffering from double enumeration?
For example, what are the telltale signs that the following code might be double enumerating? What are some other signs to look out for?
public static bool MyIsIncreasingMonotonicallyBy<T, TResult>(this IEnumerable<T> list, Func<T, TResult> selector)
where TResult : IComparable<TResult>
{
return list.Zip(list.Skip(1), (a, b) => selector(a).CompareTo(selector(b)) <= 0).All(b => b);
}
Pass in one of these:
public class OneTimeEnumerable<T> : IEnumerable<T>
{
public OneTimeEnumerable(IEnumerable<T> source)
{
_source = source;
}
private IEnumerable<T> _source;
private bool _wasEnumerated = false;
public IEnumerator<T> GetEnumerator()
{
if (_wasEnumerated)
{
throw new Exception("double enumeration occurred");
}
_wasEnumerated = true;
return _source.GetEnumerator();
}
}

How to create a generic type that takes either T or IEnumerable<T>?

Let's say I have a type:
public class Transformer<T, TResult>
where T : IMessage
where TResult : IMessage
{
private Func<T, IEnumerable<TResult>> _transformer;
public Transformer(Func<T, TResult> transformer)
{
_transformer = null // ?
}
public Transformer(Func<T, IEnumerable<TResult>> transformer)
{
_transformer = transformer;
}
}
So in essence, I'd like to convert Func<T, TResult> into Func<T, IEnumerable<TResult>> in the first constructor.
I've tried to create a private inner class that takes Func<T, TResult> and defined a method that returns IEnumerable like this:
private class TransformerWrapper
{
private readonly Func<T, TResult> _func;
public TransformerWrapper(Func<T, TResult> func)
{
_func = func;
}
public IEnumerable<TResult> Transform<T>(T message) where T : IMessage
{
yield return _func(message);
}
}
But it's not really working out. I get an error saying delegate has an invalid argument - cannot convert from T to T.
First of all, what is happening with the compiler error and second, is there another way?
Update
Minutes after I posted, I found a solution:
public Transformer(Func<T, TResult> transformer)
{
_transformer = new TransformerWrapper<T, TResult>(transformer).Transform;
}
And,
private class TransformerWrapper<T, TResult>
{
private readonly Func<T, TResult> _func;
public TransformerWrapper(Func<T, TResult> func)
{
_func = func;
}
public IEnumerable<TResult> Transform(T message)
{
yield return _func(message);
}
}
I still can't get my head around why the first solution did not work. I need to think about that one...
Try this:
public Transformer(Func<T, TResult> transformer)
{
_transformer = t => Convert(t, transformer);
}
private static IEnumerable<TResult> Convert(T value, Func<T, TResult> transformer)
{
yield return transformer(t);
}
You're specifying a new generic type T in the Transform<T> function. As T and TResult are already defined in the parent class, there's no need for anything in the child class to be generic.
Remove the <T> and the generic qualifier from the method signature and it should compile.
public IEnumerable<TResult> Transform(T message)
{
yield return _func(message);
}
Change your inner class to:
private class TransformerWrapper
{
private readonly Func<T, TResult> _func;
public TransformerWrapper(Func<T, TResult> func)
{
_func = func;
}
public IEnumerable<TResult> Transform(T message)
{
yield return _func(message);
}
}
}
Compile already knows what T is, and you don't need to constrain the method again.

Categories