Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Delegate return type different with lambda function

Consider this MCVE:

using System;

public interface IThing { }

public class Foo : IThing
{
    public static Foo Create() => new Foo();
}

public class Bar : IThing
{
    public static Bar Create() => new Bar();
}

public delegate IThing ThingCreator();

class Program
{
    static void Test(ThingCreator creator)
    {
        Console.WriteLine(creator.Method.ReturnType);
    }

    static void Main()
    {
        Test(Foo.Create);      // Prints: Foo
        Test(Bar.Create);      // Prints: Bar

        Test(() => new Foo()); // Prints: IThing
        Test(() => new Bar()); // Prints: IThing
    }
}

Why does reflecting the return type for the static factory method give the concrete type, while calling the constructor inline gives the interface? I would expect them to both be the same.

Also, is there a way to specify in the lambda version that I want the return value to be the concrete type? Or is calling a static method the only way to do that?

like image 405
Matt Johnson-Pint Avatar asked Mar 16 '17 22:03

Matt Johnson-Pint


1 Answers

The return type of a lambda expression is not inferred from what the lambda acutally returns, but from the type it is assigend to. I.e., you can not assign a lambda like this (except when generic type parameters are involed; see comments of Eric Lippert):

// This generates the compiler error:
// "Cannot assign lambda expression to an implicitly-typed variable".
var lambda = () => new Foo();

You must always do something like this (lambdas are always assigned to a delegate type):

Func<MyType> lambda = () => new Foo();

Therefore in Test(() => new Foo()); the return type of the lambda is determined from the type of the parameter it is assigned to (IThing, the return type of ThingCreator).

In Test(Foo.Create); you don't have a lambda at all, but a method declared as public static Foo Create() .... Here the type is specified explicitly and is Foo (it makes no difference whether it is a static or instance method).

like image 81
Olivier Jacot-Descombes Avatar answered Oct 03 '22 20:10

Olivier Jacot-Descombes