Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Converting Func<> types

Cannot convert type 'System.Func<int,bool>' to 'System.Func<object,bool>'

Trying to cast f2 to f1:

    Func<object, bool> f1 = x => true;
    Func<int, bool> f2 = x => true;
    f1 = (Func<object, bool>)f2;

Tried map function to solve but, this time i get

Argument 1: cannot convert from 'C' to 'A' 

exception. on tranform(a) function

    Func<int, bool> f3 = Map(f2, x => x);

    Func<C, B> Map<A, B, C>(Func<A, B> input, Func<A, C> transform)
    {
        return x => input(transform(x));
        // return x => input(transform((A)x)); not working
    }

Is there a solution?

like image 654
jack-london Avatar asked Jan 30 '13 08:01

jack-london


1 Answers

This should work:

f1 = p => f2((int)p);

Naturally, however, using this f1 will produce an InvalidCastException if you pass it something that cannot be cast to an int.

It is possible to create a generic utility function to do this, provided the input type of f2 inherits from the input type of f1 (which is true in your example - int derives from object):

static Func<TOut, TR> ConvertFunc<TIn, TOut, TR>(Func<TIn, TR> func) where TIn : TOut
{
    return p => func((TIn)p);
}

Then you can use it like this:

f1 = ConvertFunc<int, object, bool>(f2);

But that's not any more concise than my first example, and I think this second approach is somewhat less readable than the first one.


Incidentally, it is possible to get your Map() method to compile if you put the type arguments in the right order:

static  Func<TNewIn, TOut> Map<TOrigIn, TNewIn, TOut>(Func<TOrigIn, TOut> input, 
                                                      Func<TNewIn, TOrigIn> convert)
{
    return x => input(convert(x));
}

You can call it like this:

f1 = Map(f2, (object x) => (int)x);

You need to explicitly indicate the NewIn type because there's no way for the compiler to infer it.

like image 72
JLRishe Avatar answered Sep 28 '22 10:09

JLRishe