Зачем объявлять статическую локальную функцию в C # 8.0 - PullRequest
5 голосов
/ 07 ноября 2019

В C # 8.0 объявлено Статические локальные функции

Может кто-нибудь помочь мне объяснить, почему вы хотите объявить локальную функцию как статическую?

причина, приведенная в статье:

до гарантирует , что локальная функция не захватывает (не ссылается) какие-либо переменные из охватывающей области видимости

Но:

  1. Я не понимаю почему вы хотите это сделать?
  2. Есть ли какая-либо другая причина или преимущества, чтобы объявить это статическим? (производительность может быть?)

Пример кода, приведенный в статье:

int M()
{
    int y = 5;
    int x = 7;
    return Add(x, y);

    static int Add(int left, int right) => left + right;
}

Ответы [ 4 ]

5 голосов
/ 07 ноября 2019

Я не понимаю, зачем вам это нужно?

Потому что это мешает вам выстрелить себе в ногу. Это заставляет локальную функцию быть чистой функцией , которая не изменяет состояние вызывающего.

Возвращает false, потому что функция изменяет локальные переменные своего вызывающего:

public bool Is42()
{
    int i = 42;     
    Foo();      
    return i == 42;

    void Foo()
    {
        i = 21;
    }   
}

И это не так, потому что он даже не компилируется:

public bool Is42()
{
    int i = 42;     
    Foo();      
    return i == 42;

    static void Foo()
    {
        i = 21;
    }   
}

Он предотвращает неожиданности. Конечно, в этих простых примерах выгода не сразу очевидна, потому что "хорошо, очевидно, что Foo() изменяет i" , но в больших кодовых базах, поддерживаемых несколькими людьми и не должным образом покрытых модульными тестамиЭтот простой модификатор предотвращает горе.

3 голосов
/ 07 ноября 2019

Захват переменных имеет небольшую дополнительную стоимость, поскольку он генерирует внутренне используемый тип, где ваши захваченные переменные являются открытыми полями. Рассмотрим слегка измененный пример:

int M()
{
    int y = 5;
    int x = 7;
    return Add();

    int Add() => x + y;
}

На самом деле это будет выглядеть примерно так:

int M()
{
    int y = 5;
    int x = 7;
    var capturedVars = new <>c__DisplayClass0_0 { x = x, y = y };
    return <M>g__Add|0_0(ref capturedVars);
}

[CompilerGenerated]
private struct <>c__DisplayClass0_0
{
    public int x;
    public int y;
}

[CompilerGenerated]
internal static int <M>g__Add|0_0(ref <>c__DisplayClass0_0 class_Ref1) => 
    (class_Ref1.x + class_Ref1.y);
1 голос
/ 07 ноября 2019

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

0 голосов
/ 08 ноября 2019

Этот ответ от CodeCaster и это отдельный ответ от György Kőszeg индивидуально отвечает на разные части моего вопроса, поэтому я собираю их вместе, чтобы сформировать полную картину для принятогоответ:

Для Часть 1) моего вопроса, @CodeCaster говорит:

Потому что это мешает вам выстрелить себе в ногу. Это заставляет локальную функцию быть чистой функцией, которая не изменяет состояние вызывающей стороны .

в больших кодовых базах, поддерживаемых несколькими людьми и не должным образом охватываемых модульными тестами, этот простой модификаторпредотвращает горе

Итак, ответ 1: Статические локальные функции обеспечивают надежное состояние метода вызывающего абонента.

Для Часть 2) моего вопроса, @ György Kőszeg говорит:

Захват переменных имеет небольшую дополнительную стоимость, поскольку он генерирует внутренне используемый тип, где ваши захваченные переменные являются открытыми полями

И он продолжаетпривести пример созданного кода компилятора через отражатель.

Итак, ответ 2: Статические локальные функции предотвращают захват переменных. Захват переменных происходит при небольших затратах. Таким образом, небольшое повышение производительности за счет объявления статической локальной функции

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...