Почему выходной параметр не разрешен в анонимном методе? - PullRequest
14 голосов
/ 28 октября 2009

Это не обман Вызов метода с параметрами ref или out из анонимного метода

Мне интересно , почему параметры не разрешены в анонимных методах. Отказ от ref параметров имеет для меня немного больше смысла, но параметры out , не так много.

что вы думаете об этом

Ответы [ 4 ]

29 голосов
/ 28 октября 2009

В некотором смысле это обман. Out параметры - ref параметры. У значения просто есть дополнительный атрибут, который используется языком C #. Причина их запрета точно такая же, как у ref параметров.

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

Представьте, например, что параметр out ссылается на локальную переменную в стеке. Лямбда может выполняться в любой произвольной точке в будущем и, следовательно, может выполняться, когда этот кадр стека больше не действителен. Что тогда будет означать параметр out? 1011 *

6 голосов
/ 28 октября 2009

Это в основном связано с тем фактом, что параметры анонимного делегата / лямбда-выражения захваченные переменные , а захват ref / out переменных не имеет никакого смысла в C # / CLR, поскольку для этого потребуется внутренне ref / out полей . Также обратите внимание, что я связываю оба этих ключевых слова, потому что они фактически одинаковы.

Если вы хотите получить полное объяснение, Эрик Липперт подробно обсудил этот вопрос в своем блоге. (См. Параграфы в нижней части, в частности.)

1 голос
/ 16 января 2012

Я столкнулся с этой загадкой, когда разрабатывал некоторый код обработки ошибок. Я хотел передать ссылку (out) на сообщение об ошибке, которое будет зарегистрировано. Это дало моим анонимным методам возможность выполнить несколько проверок, каждая из которых при необходимости установила сообщение об ошибке.

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

    protected delegate void OutStringDelegate(int divider, out string errorText);
    protected void codeWrapper(int divider, OutStringDelegate del)
    {
        string ErrorMessage = "An Error Occurred.";

        try
        {
            del(divider, out ErrorMessage);
        }
        catch
        {
            LogError(ErrorMessage);
        }
    }
    public void UseWrapper(int input)
    {
        codeWrapper(input, codeToCall);
    }
    private int somePrivateValue = 0;
    private void codeToCall(int divider, out string errorMessage)
    {
        errorMessage = "Nice Error Message here!";
        somePrivateValue = 1 / divider; // call me with zero to cause error.
    }
    private void LogError(string msg)
    {
        Console.WriteLine(msg);
    }
1 голос
/ 28 октября 2009

Единственная разница между параметрами out и ref заключается в том, что к параметру out будет применен токен [out]. Для CLR это одно и то же.

Чтобы реализовать это, компилятор должен сгенерировать ref полей , которые не поддерживаются.

Если вы подумаете об этом, вы поймете, что бессмысленно разрешать анонимному методу использовать параметр out.

К чему бы следующий код?

static Func<object, object> Mess(out object param) {
    param = "Original";
    return i => param = i;
}
static Func<object, object> MessCaller() {
    object local;
    return Mess(out local);
}
static vouid Main() {
    Console.WriteLine(MessCaller()("New"));
    //The local variable that the lambda expression writes to doesn't exist anymore.
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...