11 ответов:
Вы можете имитировать его с помощью делегата... Вот мой пример кода:
public Func<int> Increment() { int num = 0; return new Func<int>(() => { return num++; }); }вы можете назвать это так:
Func<int> inc = Increment(); inc();
потому что они облажались, и оставили полезную функцию, чтобы удовлетворить себя.
все аргументы о том, как вы должны кодировать, и что умно, и вы должны пересмотреть свой образ жизни, являются напыщенными защитными оправданиями.
конечно, C# является чистым и ориентированным на whatchamacallit. Вот почему они автоматически генерируют постоянные локальные значения для лямбда-функций. Это все так сложно. Я чувствую себя так глупо.
loop scope static полезен и важен во многих случаях случаи.
короткий, реальный ответ, вы должны переместить локальную статику в область класса и жить с загрязнением пространства имен классов в C#. Принять вашу жалобу в мэрию.
состояние обычно является частью объект и частью тип, не является частью метода. (Исключение составляют захваченные переменные, конечно.)
Если вам нужен эквивалент локальной статической переменной, создайте переменную экземпляра или статическую переменную - и подумайте, должен ли сам метод быть частью другого типа с этим состоянием.
запись в блоге MSDN почему C# не поддерживает статические переменные метода? имеет дело с точным вопросом, заданным в исходном сообщении:
есть две причины, по которым C# не имеет этой функции.
во-первых, можно получить почти тот же эффект, имея статика на уровне класса и добавление статики метода потребовали бы увеличения сложность.
во-вторых, статика уровня метода несколько печально известна вызывающий проблемы, когда код вызывается повторно или из нескольких потоков, и поскольку определения находятся в методах, труднее найти определение.
[автор: Эрик Gunnerson]
Я не так хорошо знаком с C, как с C#, но я считаю, что вы можете выполнить все, что можете, с помощью локальной статики, используя статику уровня класса, которая используется только для одного метода. Очевидно, что это связано с некоторыми синтаксическими изменениями, но я считаю, что вы можете получить любую необходимую вам функциональность.
кроме того, Эрик Липперт отвечает на подобные вопросы на своем блог много. Вообще ответил в таким образом: "меня спрашивают" почему C# не реализует функцию X?"все время. Ответ всегда один и тот же: потому что никто никогда не проектировал, не определял, не реализовывал, не тестировал, не документировал и не отправлял эту функцию."По существу, его ответы обычно сводятся к тому, что добавление какой-либо функции стоит денег, и поэтому многие потенциальные функции не реализуются, потому что они не вышли на положительную сторону анализа затрат и выгод.
Итак, вы хотите использовать статическую локальную переменную в методе? Поздравляю! Вы сделали еще один шаг к тому, чтобы стать реальные программист.
Не слушайте всех людей, которые говорят вам, что статические местные жители не "чисты", что они препятствуют "читаемости" и могут привести к тонким и труднодоступным "ошибкам". Чепуха! Они просто говорят это, потому что они киноман программисты! Многие из них, вероятно, даже играют с эзотерическим функционалом язык программирования в свободное от работы время. Ты можешь в это поверить? Какая кучка хипстеров!
реальные программисты принимают парадигму, которую я люблю называть SDD -Sэффект ide DРивен Dконструкции. Вот некоторые из самых важных законов:
не будьте предсказуемы! никогда не возвращайте одно и то же из метода дважды-даже если он вызывается с точным те же аргументы!
винт чистоты-давайте пачкаться! государство, по своей природе, жаждет перемен, потому что оно ненасытный моноид в категории полиаморных эндофункторов, то есть он любит, чтобы его коснулось как можно больше сотрудников. Никогда не упускайте возможность сделать ему одолжение!
среди инструментов, используемых для кодирования в побочном эффекте управляемым образом, конечно, статические локальные переменные. Однако, как вы заметили, с# не поддерживает их. Зачем? Потому что за последние два десятилетия Microsoft была проникнута так называемым Чистые Кодеры это благоприятствует ремонтопригодности над гибкостью и контролем. Можете ли вы даже вспомнить, когда в последний раз вы видели наш любимый синий экран? Теперь угадайте, чья это вина!
но не бойся! реальные разработчики не должны страдать от этих плохих проектных решений. Как уже упоминалось ранее можно иметь местные переменные, которые являются своего рода статическими с помощью лямбд.
однако, предоставленное решение не было вполне удовлетворительным. Используя предыдущий ответ наш почти SDD-совместимый код будет выглядеть примерно так:
var inc = Increment(); var zero = inc(); var one = inc();или
var zero = Increment()();но это просто глупо. Даже киноман разработчик может видеть, что
Increment()не является нормальным методом и будет подозрительным. А реальные программист, с другой стороны, можно сделать это еще более SDD-как. Он или она знает, что мы можем сделать свойство или поле похожим на метод, придав ему типFunc<T>! Нам просто нужно инициализировать его, выполнив лямбду, которая в свою очередь инициализирует счетчик и возвращает другую лямбду, увеличивающую захваченный счетчик!вот он в правильном SDD-коде:
public Func<int> Increment = new Func<Func<int>>(() => { var num = 0; return () => num++; }).Invoke();(вы думаете, что выше вроде выглядит как IIFE? Да, вы правы и вам должно быть стыдно себе.)
теперь каждый раз, когда вы называете
Increment()он вернет что-то другое:var zero = Increment(); var one = Increment();конечно, вы также можете сделать так, что счетчик переживает время жизни вашего экземпляра.
это покажет им киноман программисты!
C# является компонентно-ориентированным языком и не имеет понятия переменных вне области действия класса или локального метода. Переменные внутри метода также не могут быть объявлены статическими, как вы привыкли делать в C. Однако вы всегда можете использовать статическую переменную класса в качестве замены.
Как правило, существуют способы решения проблем программирования в C#, не прибегая к использованию статики на уровне метода. Государство, как правило, то, что вы должны проектировать на классы и типы, а не методы.
логично, да. Это будет то же самое, что и статический элемент уровня класса, который использовался только в этом одном методе. Однако статический элемент уровня метода будет более инкапсулирован. Если данные, хранящиеся в элементе, предназначены только для использования одним методом, они должны быть доступны только этим одним методом.
однако вы можете достичь почти такого же эффекта в C#, создав вложенный класс.
потому что статические локальные переменные привязаны к методу, и метод является общим для всех экземпляров.
Я должен исправить себя и других программистов, которые ожидали, что он будет уникальным для каждого экземпляра класса с помощью метода.
однако, если вы сделаете его статическим классом или статическим экземпляром класса, синтаксически ясно, есть ли экземпляр для класса-контейнера или один экземпляр вообще.
Если вы не используете их, становится легче рефакторинг позже.
Я думаю, что идея локальной статики так же легко решается путем создания общедоступных статических полей в классе. Очень мало логических изменений, не так ли?
Если вы думаете, что это будет большой логичное изменение, мне было бы интересно услышать, как.
class MyClass { public static float MaxDepthInches = 3; private void PickNose() { if (CurrentFingerDepth < MyClass.MaxDepthInches) { CurrentFingerDepth++; } } }
Если вы можете представить себе какой-то гибридный объект Липперта/Фарнсворта, объявляющий ХОРОШИЕ НОВОСТИ ВСЕ! в C# 6.0 позволяет
using staticзаявление. Это эффективно позволяет импортировать статические методы класса (и, похоже, свойства и члены) в глобальную область.короче говоря, вы можете сделать что-то вроде этого:
using NUnit.Framework; using static Fizz.Buzz; class Program { [Test] public void Main() { Method(); int z = Z; object y = Y; Y = new object(); } } namespace Fizz { class Buzz { public static void Method() { } public static int Z; public static object Y { get; set; } } }хотя это доступно только в C# 6.0, из того, что я понимаю, сгенерированные сборки должны быть совместимы предыдущие платформы .NET (поправьте меня, если я ошибаюсь).
Comments