Почему выходной параметр не разрешен в анонимном методе?

StackOverflow https://stackoverflow.com/questions/1637863

Вопрос

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

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

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

Это было полезно?

Решение

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

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

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

Другие советы

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

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

Единственное различие между параметрами 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.
}

Я столкнулся с этой загадкой при разработке кода обработки ошибок. Я хотел передать ссылку (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);
    }
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top