3

Consider the following example:

class Program
{
    private static void Main(string[] args)
    {
        Foo(() => { });
        Foo(() => { throw new Exception(); });
        Foo(() => { Throws(); });
        Foo(() => { throw new Exception(); return; });
        Foo(() => { throw new Exception(); return true; });
        Console.ReadLine();
    }

    public static void Foo(Action a)
    {
        Console.WriteLine("Foo(Action)");
    }

    public static void Foo(Func<bool> f)
    {
        Console.WriteLine("Foo(Func<bool>)");
    }

    public static void Throws()
    {
        throw new Exception();
    }
}

Which has the following output:

Foo(Action)
Foo(Func<bool>)
Foo(Action)
Foo(Action)
Foo(Func<bool>)

I was quite surprised to notice that Foo(() => { throw new Exception(); }); invokes the Foo(Func<bool> f) overload. I would expect it to invoke the other overload. Also notice that Foo(() => { throw new Exception(); return; }); invokes Foo(Action a).

This behavior seems inconsistent. I cannot find the reason for this. It appears that when the compiler detects that the lambda always throws it will favor the Foo(Func<bool> f) overload, however adding a return statement that never will be reached, will change the behavior. Why does it behave like this?

André
  • 460
  • 6
  • 18
  • If you try any function with a return value and just add a Throw new Exception(); without anything else you can see the compiler does not complain about missing return, so this is the correct behavior even if it seems it's not (what I have no clue is which type of return object will use, maybe object?). – Gusman Mar 21 '16 at 17:38
  • 1
    Methods with `while(true)`, `throw new Exception` are compatible to delegates with any return type. Refer the linked duplicate for more info. – Sriram Sakthivel Mar 21 '16 at 17:39

0 Answers0