Passing lambda functions as named parameters in C#

前端 未结 3 1709
春和景丽
春和景丽 2021-01-31 15:54

Compile this simple program:

class Program
{
    static void Foo( Action bar )
    {
        bar();
    }

    static void Main( string[] args )
    {
        Fo         


        
3条回答
  •  小蘑菇
    小蘑菇 (楼主)
    2021-01-31 16:34

    Note: Not really an answer, but far too big for a comment.

    More interesting results when you throw in type-inference. Consider this code:

    public class Test
    {
        public static void Blah(Action blah)
        {
        }
    
        public static void Main()
        {
            Blah(x => { Console.LineWrite(x); });
        }
    }
    

    It won't compile, because there's no good way to infer what T should be.
    Error Message:

    The type arguments for method 'Test.Blah(System.Action)' cannot be inferred from the usage. Try specifying the type arguments explicitly.

    Makes sense. Let's specify the type of x explicitly and see what happens:

    public static void Main()
    {
        Blah((int x) => { Console.LineWrite(x); });
    }
    

    Now things go awry because LineWrite doesn't exist.
    Error Message:

    'System.Console' does not contain a definition for 'LineWrite'

    Also sensible. Now let's add in named arguments and see what happens. First, without specifying the type of x:

    public static void Main()
    {
        Blah(blah: x => { Console.LineWrite(x); });
    }
    

    We would expect to get an error message about not being able to infer type arguments. And we do. But that's not all.
    Error Messages:

    The type arguments for method 'Test.Blah(System.Action)' cannot be inferred from the usage. Try specifying the type arguments explicitly.

    'System.Console' does not contain a definition for 'LineWrite'

    Neat. Type inference fails, and we're told exactly why the lambda conversion failed. Ok, so let's specify the type of x and see what we get:

    public static void Main()
    {
        Blah(blah: (int x) => { Console.LineWrite(x); });
    }
    

    Error Messages:

    The type arguments for method 'Test.Blah(System.Action)' cannot be inferred from the usage. Try specifying the type arguments explicitly.

    'System.Console' does not contain a definition for 'LineWrite'

    Now that is unexpected. Type inference is still failing (I assume because the lambda -> Action conversion is failing, thus negating the compiler's guess that T is int) and reporting the cause of the failure.

    TL; DR: I'll be glad when Eric Lippert gets around to looking at the heuristics for these more complex cases.

提交回复
热议问题