views:

611

answers:

2

Type of conditional expression cannot be determined because there is no implicit conversion between 'lambda expression' and 'lambda expression'

Say whaat? Could someone please explain this compile error to me? This is the code that produces it:

    protected override Func<System.IO.Stream> GetStream()
    {
        return someBool
            ? () => EmbeddedResourceExtractor.GetFile("SomeFile1.ext")
            : () => EmbeddedResourceExtractor.GetFile("SomeFile2.ext");
    }

This does not:

    protected override Func<System.IO.Stream> GetStream()
    {
        return () => EmbeddedResourceExtractor.GetFile("SomeFile1.ext");
    }

And neither do this:

    protected override Func<System.IO.Stream> GetStream()
    {
        if(someBool)
            return () => EmbeddedResourceExtractor.GetFile("SomeFile1.ext");
        return () => EmbeddedResourceExtractor.GetFile("SomeFile2.ext");
    }
+6  A: 

The type of the conditional expression has to be inferred as a whole - and lambda expressions always have to be converted to a specific delegate or expression tree type.

In your latter two examples, the compiler knows what it's trying to convert the lambda expression to. In the first example, it tries to work out the type of the whole conditional expression first.

A cast in one of the branches would be enough though:

protected override Func<Stream> GetStream()
{
    return someBool
        ? (Func<Stream>)
          (() => EmbeddedResourceExtractor.GetFile("SomeFile1.ext"))
        : () => EmbeddedResourceExtractor.GetFile("SomeFile2.ext");
}

Sergio's fix (now deleted, but included below) will work if you were happy to evaluate someBool at the time the function is called:

protected override Func<Stream> GetStream()
{
    return () => someBool
          ? EmbeddedResourceExtractor.GetFile("SomeFile1.ext")
          : EmbeddedResourceExtractor.GetFile("SomeFile2.ext");
}

Depending on timing, there are all kinds of different ways of fixing the example you've actually given, e.g.

protected override Func<Stream> GetStream()
{
    string name = someBool ? "SomeFile1.ext" : "SomeFile2.ext";
    return () => EmbeddedResourceExtractor.GetFile(name);
}

I'm guessing your real code is more complicated though.

It's a shame in some ways that C#'s type inference can't be more powerful - but it's already pretty complicated.

Jon Skeet
With the exception of having to wrap the first branch in parenthesis, that worked yes... Hope they can make the C#'s type inference even better in the future. Although, it is pretty nice already =)
Svish
Nice options, actually hadn't thought of any of them. But those will make it clearer yes :)
Svish