Должны ли статические статические методы С#, которые * могут быть статическими?

Если методы С#, которые могут быть статическими, являются статическими?

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

Вопрос: должен ли он быть статичным? Это не статично по дизайну или выбору, просто по своей природе, поскольку оно не ссылается ни на какие значения экземпляра.

Ответы

Ответ 1

Это зависит. Существуют действительно 2 типа статических методов:

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

В базе кода малого и среднего размера вы можете рассматривать оба метода взаимозаменяемо.

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

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

Это может привести к:

  • Много дублирования кода
  • Взрыв числа аргументов метода

Обе эти вещи плохие.

Итак, мой совет будет заключаться в том, что если у вас есть база кода более 200 тыс. LOC, я бы только ставил методы статическими, если они являются обязательными статическими методами.

Рефакторинг от нестатического к статическому относительно просто (просто добавьте ключевое слово), поэтому, если вы хотите позже сделать статическую статическую в фактическую статическую (если вам нужна ее функция за пределами экземпляра), то ты можешь. Тем не менее, обратный рефакторинг, превращающий can-be-static в метод экземпляра, намного дороже.

С большими базами кода лучше ошибиться на стороне простоты расширения, а не на стороне идеальной чистоты.

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

Ответ 2

Я бы не стал публичным статическим членом этого класса. Причина в том, что сделать его public static говорит что-то о типе класса: не только это "этот тип знает, как это сделать", но также "ответственность за это поведение несет именно этот тип". И вероятность того, что поведение больше не имеет реальных отношений с более крупным типом.

Это не значит, что я бы не стал статичным вообще. Спросите себя: может ли новый метод логически принадлежать другому? Если вы можете ответить "да" на это, вы, вероятно, захотите сделать его статическим (и переместить его также). Даже если это не так, вы все равно можете сделать его статичным. Просто не отмечайте его public.

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

Ответ 3

Не обязательно.

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

Ответ 4

Да. Причиной "он может быть статичным" является то, что он не работает с состоянием объекта, на который он вызван. Поэтому это не метод экземпляра, а метод класса. Если он может делать то, что ему нужно, не обращаясь к данным для экземпляра, тогда он должен быть статическим.

Ответ 5

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

Ответ 6

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

Ответ 7

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

Ответ 8

Лично я большой поклонник безгражданства. Требуется ли вашему методу доступ к состоянию класса? Если ответ отрицательный (и это, вероятно, нет, в противном случае вы не станете считать его статическим методом), тогда да, идите на него.

Отсутствие доступа к состоянию - это меньше головной боли. Так же, как хорошая идея скрыть частных членов, которые не нужны другим классам, неплохо скрыть состояние от членов, которые не нуждаются в этом. Уменьшенный доступ может означать меньше ошибок. Кроме того, он упрощает процесс нарезания резьбы, так как гораздо проще сохранять статические элементы в потоковом режиме. Также есть соображение производительности, так как во время выполнения не требуется передавать ссылку на this в качестве параметра для статических методов.

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

Так что да, идите на это, во что бы то ни стало.

Ответ 9

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

Как сказал Майкл, изменение этого позже приведет к слому кода, использующего его.

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

Ответ 10

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

Ответ 11

Я удивлен, что на самом деле так мало упоминается инкапсуляция. Метод экземпляра автоматически получит доступ ко всем частным (экземплярам) полям, свойствам и методам. В дополнение ко всем защищенным, унаследованным от базовых классов.

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

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

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

Ответ 12

Лично у меня не было бы выбора, кроме как сделать его статичным. В этом случае Resharper выдает предупреждение, и у нашего PM есть правило "Нет предупреждений от Resharper".

Ответ 13

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

Ответ 14

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

Ответ 15

Вы должны подумать о своих методах и классах:

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

Если последние два являются "да", то ваш метод/класс должен быть, вероятно, статическим.

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

Другим хорошим примером является метод Reverse() в С#.
Это статический метод в классе Array, Он меняет порядок вашего массива.

код:

public static void Reverse(Array array)

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

Ответ 16

Я бы определенно превратил все, что мог, в статику по другой причине:

Статические функции, когда JIT'd, вызываются без параметра "this". Это означает, например, что трехстатистическая нестатическая функция (метод-член) нажимается с 4 параметрами в стеке.

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

Ответ 17

Я нахожусь в статичном лагере "только сделай приватные методы". Создание общедоступного метода может привести к сочетанию, которое вы не хотите, и может уменьшить тестируемость: вы не можете заглушить открытый статический метод.

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

Ответ 18

Постоянные статические методы, которые по какой-то причине делают нестатические, просто раздражают. К остроумию:

Я звоню в свой банк и спрашиваю о моем балансе.
Они просят номер моего счета. Достаточно честный. Метод экземпляра.

Я звоню в свой банк и спрашиваю их почтовый адрес.
Они запрашивают мой номер счета.
WTF? Fail — должен был быть статическим методом.

Ответ 19

Пока вы создаете новый метод private static, он не является изменением. Фактически, FxCop включает это руководство в качестве одного из своих правил (http://msdn.microsoft.com/en-us/library/ms245046(VS.80).aspx) со следующей информацией:

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

Итак, первый комментарий Дэвида Кина более кратко излагает проблемы, говоря, что на самом деле это скорее правильное, чем увеличение производительности:

Хотя это правило классифицируется как проблема с производительностью, повышение производительности при создании статического метода составляет всего около 1%. Скорее, это скорее проблема правильности, которая может указывать либо на неполную, либо на ошибку в члене из-за неспособности использовать другие члены экземпляра. Маркировка метода static ( Shared в Visual Basic) дает понять о своем намерении не касаться состояния экземпляра.

Ответ 20

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

Ответ 21

В этих случаях я склонен переместить метод в статическую или utils-библиотеку, поэтому я не смешиваю понятие "объект" с понятием "класс"