Почему круглые скобки вокруг лямбда-оператора вызывают синтаксическую ошибку? - PullRequest
10 голосов
/ 07 февраля 2011

Я ищу хорошее объяснение, почему один фрагмент кода не компилируется, а другой компилируется просто отлично.

Сбои:

richTextBox1.Invoke(new MethodInvoker((() => { richTextBox1.AppendText("test"); })));

Выдает ошибку

Ожидается имя метода

в открывающей скобке сразу после MethodInvoker(.Видимо, я не могу заключить свои лямбда-выражения в скобки.

Компиляции:

richTextBox1.Invoke(new MethodInvoker(() => { richTextBox1.AppendText("test"); }));

Вопросы - почему?

Я всегда считал само собой разумеющимся, что могу заключить любой параметр метода в скобки, если захочу, но, видимо,не в случае с лямбда-выражениями.Я понимаю, что они несколько особенные, но я до сих пор не вижу веских причин для этого.Может быть, я не понимаю что-то о синтаксисе.Я бы очень хотел получить его.

Кстати, это присутствует в VS2008, .NET 3.5 SP1, я еще не тестировал его в VS2010 и .NET 4.

Ответы [ 3 ]

7 голосов
/ 07 февраля 2011

Это не лямбда-выражение, это выражение в скобках, которое содержит лямбда-выражение.Следовательно, узел для этого параметра в абстрактном синтаксическом дереве для этого вызова метода будет выражением в скобках, а не лямбда-выражением, как того требует спецификация.Вот почему.

В других местах компилятор Microsoft C # нарушает спецификацию и принимает такое выражение, даже если это не должно (в соответствии со спецификацией), но это не одно из них.

Соответствующий раздел спецификации - §6.5.

4 голосов
/ 07 февраля 2011

Вы ошибаетесь в предположении, что вы написали «параметр метода». Созданная вами конструкция не является вызовом метода, вы написали выражение создания делегата (см. Спецификацию C #, раздел 7.6.10.5), которое должно иметь один аргумент, который должен быть либо

  • группа методов,
  • анонимная функция или
  • значение динамического типа компиляции или типа делегата.

В вашем случае это не группа методов (в сообщении об ошибке указывается, что там ожидается имя метода), ни анонимная функция (поскольку это выражение, которое «где-то внутри» содержит анонимную функцию), ни значение указанных типов.

Если вы написали вызов метода, вы действительно можете заключить параметр в скобки, даже если он содержит лямбда-выражение:

void Method(Action action)
{
}
...
Method((() => { Console.WriteLine("OK"); }));
3 голосов
/ 07 февраля 2011

Поскольку компилятор ожидает ()=>{} внутри метода Invoke() и в первом примере он не находит его. Все в круглых скобках вычисляется сначала, возвращая единственный объект, и в этом случае компилятор ожидает ссылку на делегат.

Отредактировано Я решил ту же проблему с этим методом расширения:

    public delegate void EmptyHandler();
    public static void SafeCall(this Control control, EmptyHandler method) 
    {
        if (control.InvokeRequired)
        {
            control.Invoke(method);
        }
        else
        {
            method();
        }
    } 

Так что вы можете позвонить

RichTextBox rtb = new RichRextBox();
...

rtb.SafeCall( ()=> rtb.AppendText("test") );
...