12
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?

jack-london
  • 1,599
  • 3
  • 21
  • 42
  • can you please explain why you need function type casting? do you want to use one function in place of another? – D J Jan 30 '13 at 09:30
  • i need some function in a generic level component, but this function is related to implementation. and i dont want to generic-component know this implementation details. that's why i have to use this kind of casting – jack-london Jan 30 '13 at 09:49
  • You are committing type errors here. It is simply not the case, that a function from int to bool is a function from anything to bool. Rethink your design. – Ingo Jan 30 '13 at 10:55

1 Answers1

15

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.

JLRishe
  • 99,490
  • 19
  • 131
  • 169
  • 1
    this will not type cast the function it will rather change the implementation of f1 to f2. If I have ` Func f1 = x => false;` Then your method will always return true as it is no more f1 but f2. I dont think its correct answer. – D J Jan 30 '13 at 09:18
  • @DJ Isn't that what the question is asking to do? It's trying to change the implementation of `f1` to `f2` by doing a cast on `f2`. – JLRishe Jan 30 '13 at 09:22
  • 1
    I never see any statement that say this. – D J Jan 30 '13 at 09:23
  • @DJ I think it's pretty clear when he tries to use this line `f1 = (Func)f2;`. This (if it worked) would overwrite `f1` with `f2`. What do you think he's trying to do? – JLRishe Jan 30 '13 at 09:32