Вопрос по c#, static – Почему C # не поддерживает локальные статические переменные, как C?
==========================================================================================

Почему в C # нет локальных статических переменных, таких как C? Мне этого не хватает!!

object или частьtypeне является частью метода. (Исключение составляют захваченные переменные, конечно.)

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



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

Как правило, есть способы решения проблем программирования на C # без использования статики на уровне методов. Состояние - это обычно то, что вы должны проектировать в классы и типы, а не в методы.



 что идея локальной статики так же легко решается путем создания открытых статических полей для класса. Как вы думаете, очень мало логических изменений?

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



 и метод является общим для всех экземпляров.

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

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

Если вы ими не пользуетесь, то и рефакторинг станет легче позже.



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

Кроме того, Эрик Липперт отвечает на такие вопросы на своем[блог](https://blogs.msdn.com/ericlippert/) много. Вообще ответил в[сюда](https://blogs.msdn.com/ericlippert/archive/2009/06/22/why-doesn-t-c-implement-top-level-methods.aspx): "Меня спрашивают", почему "C # не реализует функцию X?" все время. Ответ всегда один и тот же: потому что никто никогда не проектировал, не определял, не реализовывал, не тестировал, не документировал и не поставлял эту функцию. & Quot; По сути, его ответы, как правило, сводятся к тому, что добавить какую-либо функцию стоит денег, и, следовательно, многие потенциальные функции не реализованы, поскольку они не проявили положительной стороны анализа затрат и выгод.



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

Тем не менее, вы можете достичь почти такого же эффекта в C #, создав вложенный класс.



[Почему C # не поддерживает статические переменные метода?](https://blogs.msdn.com/b/csharpfaq/archive/2004/05/11/why-doesn-t-c-support-static-method-variables.aspx) имеет дело с точным вопросом, заданным в оригинальном сообщении:

There are two reasons C# doesn't have this feature.

First, it is possible to get nearly the same effect by having a
class-level static, and adding method statics would require increased
complexity.

Second, method level statics are somewhat notorious for causing
problems when code is called repeatedly or from multiple threads, and
since the definitions are in the methods, it's harder to find the
definitions.

[Author: [Eric Gunnerson]](https://blogs.msdn.com/b/ericgu/)



Вы можете назвать это так:



того. Поскольку C # ограничивает область действия статических переменных классами, вы можете использовать nested-class в качестве области действия.

Например:

Вот`Foo` опоры`Increment` метод, но его поддержка частным вложенным классом`IncrementInternal` который содержит статическую переменную в качестве члена. И, конечно же,`counter` не виден в контексте (другие методы)`Foo`.

Кстати, если вы хотите получить доступ к`Foo` контекст (другие члены и методы) внутри`IncrementInternal.Increment`, вы можете пройти`this` в качестве параметра для`IncrementInternal.Increment` когда вы звоните из`Foo`.

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

Я думаю, что это чище, чем анонимные функции или IIFE.

Вы можете увидеть живую демонстрацию[Вот](https://dotnetfiddle.net/FveMbG).



 чтобы удовлетворить себя.

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

Несомненно, C # является чистым и whatchamacallit-ориентированным. Вот почему они автоматически генерируют постоянные локальные значения для лямбда-функций. Все так сложно. Я чувствую себя так глупо

Статическая петля полезна и важна во многих случаях.

Короткий, реальный ответ: вы должны переместить локальную статику в область действия класса и жить с загрязнением пространства имен класса в C #. Подайте жалобу в мэрию.



ворт, объявляющую[ХОРОШИЕ НОВОСТИ ВСЕМ!](https://www.youtube.com/watch?v=YRCzEqkCoiM)C # 6.0 позволяет`using static` заявление. Это позволяет эффективно импортировать методы статического класса (а также свойства и члены) в глобальную область видимости.

Короче говоря, вы можете сделать что-то вроде этого:

Хотя это доступно только в C # 6.0, насколько я понимаю, сгенерированные сборки должны быть совместимы с предыдущими платформами .NET (поправьте меня, если я ошибаюсь).



 вы хотите использовать статическую локальную переменную в своем методе? Поздравляем! Вы сделали еще один шаг к тому, чтобы статьreal программист.

Не слушайте всех людей, говорящих вам, что статические локальные объекты не являются «чистыми», что они препятствуют «читабельности» и может привести к неуловимым и труднодоступным «ошибкам». Ерунда! Они просто говорят это, потому что ониwannabe программисты! Многие из них, вероятно, даже играют с эзотерическим функциональным языком программирования в свободное время. Ты можешь в это поверить? Какая куча хипстеров!

Real программисты принимают парадигму, которую я люблю называтьSDD - **S**ide effect **D**riven **D**esign, Вот некоторые из наиболее важных законов:

**Don't be predictable!** Never return the same thing from a method twice - even if it's being called with the exact same arguments!

**Screw purity - let's get dirty!** State, by nature, craves changing, because it is an [insatiable monoid in the category of polyamorous endofunctors](https://stackoverflow.com/questions/3870088/a-monad-is-just-a-monoid-in-the-category-of-endofunctors-whats-the-issue), i.e. it likes to be touched by as many collaborators as possible. Never miss out on an opportunity to do it the favor!

Среди инструментов, используемых для кодирования побочным эффектом, есть, конечно же, статические локальные переменные. Однако, как вы заметили, C # не поддерживает их. Зачем? Потому что за последние два десятилетия**Microsoft has been infiltrated by so called Clean Coders** что поддерживает ремонтопригодность, а не гибкость и контроль. Можете ли вы вспомнить, когда в последний раз видели наш любимый синий экран? Теперь угадайте, чья это вина!

Но не бойся!Real разработчики не должны страдать от этих плохих дизайнерских решений. Как уже упоминалось ранее, с помощью лямбды можно иметь локальные переменные, которые являются своего рода статическими.

Однако предоставленное решение не было вполне удовлетворительным. С использованием[предыдущий ответ](https://stackoverflow.com/a/24760689/1025555) наш почти SDD-совместимый код будет выглядеть примерно так:

или же

Но это просто глупо. Дажеwannabe разработчик может видеть, что`Increment()` это не нормальный метод и станет подозрительным.real программист, с другой стороны, может сделать его еще более SDD-подобным. Он или она знает, что мы можем сделать свойство или поле похожим на метод, задав ему тип`Func<T>`! Нам просто нужно инициализировать его, выполнив лямбду, которая, в свою очередь, инициализирует счетчик и возвращает другую лямбда, увеличивающую захваченный счетчик!

Вот это в правильном SDD-коде:

(Вы думаете, что вышеупомянутый вид выглядит как[IIFE](https://en.wikipedia.org/wiki/Immediately-invoked_function_expression)? Да, вы правы и вам должно быть стыдно за себя.)

Теперь каждый раз, когда вы звоните`Increment()` [это вернет что-то другое](https://dotnetfiddle.net/VGO9t8):

Конечно, вы также можете сделать так, чтобы[счетчик выживает на протяжении всей жизни вашего экземпляра](https://dotnetfiddle.net/fGQ4h0).

Это покажет имwannabe программисты!