tags:

views:

81

answers:

3

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...

+1  A: 

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);
}
Adam Robinson
+1  A: 

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.

BFree
+1  A: 

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);
}
Steven
Thanks! I like this approach in that I didn't need to create a wrapper class.
Jiho Han