Есть ли смысл использовать локальные функции, если использовать их только один раз? - PullRequest
0 голосов
/ 20 мая 2018

Представьте, что у меня есть этот код:

public void Foo()
{
    // Do bar work
    // Do baz work
    // Do foobar work
}

И я понимаю, что могу (и должен, потому что это делало более чем одно) преобразовать его в:

public void Foo()
{
    bar();
    baz();
    foobar();
}

private void bar()    { /* do bar work */ }
private void baz()    { /* do baz work */ }
private void foobar() { /* do foobar work */ }

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

public void Foo()
{
    bar();
    baz();
    foobar();

    void bar()    { /* do bar work */ }
    void baz()    { /* do baz work */ }
    void foobar() { /* do foobar work */ }
}

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

Ответы [ 4 ]

0 голосов
/ 20 мая 2018

Что сделало бы вещи более аккуратными и менее беспорядочными, но все, что я действительно сделал сейчас, - это сделал метод еще длиннее, а не короче.

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

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

0 голосов
/ 20 мая 2018

Мне очень нравится идея @Mark Benningfield об использовании частичных файлов (это то, что я делаю, когда мои классы слишком большие и есть один или два uber-метода)

Моя единственная проблема с локальнымифункции в том, что они могут захватывать переменные, и не всегда ясно, делают это или нет.Таким образом, «продвигая» «настоящий» метод на «локальный», вы увеличиваете его видимость.

0 голосов
/ 20 мая 2018

Локальные функции обеспечивают преимущества перед анонимными функциями, потому что анонимные функции могут вызываться только через делегаты, что, помимо выделения памяти для делегата, является более дорогим вызовом.

Локальные функции могут быть рекурсивными без хитрости, необходимойделегаты:

int f(int i) => i >= 1 ? i * f(i - 1) : 1;

Func<int,int> d = null;
d = (int i) => i >= 1 ? i * d(i - 1) : 1;

Как и анонимные делегаты, локальные функции, в отличие от методов верхнего уровня, могут захватывать локальные переменные.А поскольку они локальны, они не могут быть вызваны другими функциями.

0 голосов
/ 20 мая 2018

Используйте анонимные функции:

public void Foo()
{
    Action bar = delegate () { /* do bar work */ };
    Action baz = delegate () { /* do baz work */ };
    Action foobar = delegate () { /* do foobar work */ };

    bar();
    baz();
    foobar();
}

или синтаксис лямбда-выражения:

public void Foo()
{
    Action bar = () => { /* do bar work */ };
    Action baz = () => { /* do baz work */ };
    Action foobar = () => { /* do foobar work */ };

    bar();
    baz();
    foobar();
}
...