2016-08-01 4 views
3

я могу назвать непустую функцию от лямбда, который назначен на действия (который ожидает пустой типа возвращаемого значения):Нужно ли lambdas назначать void делегату отказаться от невостребованного типа возврата в C#?

static bool foo() { return true; } 
... 
// Action action = foo; // This gives a compile error though. 
Action action =()=>foo(); // This compiles 

Сначала я заметил это, глядя на примере List.ForEach(). Я мог бы выполнить функцию non-void из лямбды и скомпилировать ее.

Вначале это казалось противоречивым и заставило меня думать, что вы можете назначить непустые функции делегату void (void действует как своего рода контравариантный), но Action action = foo; не работает.

Итак, теперь я предполагаю, что происходит то, что лямбда становится недействительной, потому что это ожидаемый тип возвращаемого значения, поэтому он отбрасывает возвращаемый тип не-void-функции, которую он вызывает. Это верно?

ответ

3

Ваш пример

Action action =()=>foo(); 

точно так же как и любой другой метод:

public void MyTestMethod() 
{ 
    // do something 
    foo(); 
    // do some more 
} 

Это абсолютно легально в C# (хотя некоторые статические анализаторы предупредит вас, что вы не используете foo() «S возвращаемое значение).

Второй пример:

action = foo; 

не работает, потому что foo сам по себе является метод с типом возврата, и для этого может быть назначен только на переменную типа Func<bool>, но не Action. С другой стороны, lambda () => foo() не имеет типа возврата и является действительным Action.

+0

Да, это имеет смысл. Я предполагаю, что это было просто математическое обозначение 'x => f (x)', что заставляет его выглядеть на первый взгляд интуитивно понятным. Благодарю. – sashoalm

2

Ну, в этой строке кода:

Action action =()=> foo(); // This compiles 

Вы на самом деле создать еще один метод, который запускает вашу функцию, используя closure:

void AnonymousMethod() 
{ 
    foo(); 
} 

Чтобы назначить другой метод делегата, который вызывает метод foo - это не то же самое, что назначить метод foo для делегирования напрямую. И вот почему строка кода:

Action action = foo; 

не будет компилироваться, потому что Action делегат имеет тип возвращаемого недействительным и метод foo не делает.