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


103

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

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

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


1
Достаточно точный дубликат stackoverflow.com/questions/169378/…
JasonTrue 08

41
«довольно точно» - это оксюморон
Мэтт Бриггс

1
Resharper , инструмент для Visual Studio, говорит: да! :-)
Ребекка

@Junto Может быть, в вашей версии, но моя говорит, что это можно сделать статичным ...
Робби Ди

Ответы:


59

Это зависит. На самом деле существует 2 типа статических методов:

  1. Статические методы, потому что они МОГУТ быть
  2. Статические методы, потому что они ДОЛЖНЫ быть

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

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

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

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

  1. Много дублирования кода
  2. Резкий рост количества аргументов метода

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

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

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

При больших базах кода лучше делать ошибки из-за простоты расширения, а не из-за идеологической чистоты.

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


43

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

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

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


6
Согласовано. Я обычно делаю метод "приватным статическим" в таком случае.
harpo

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

1
Например: «может ли новый метод логически принадлежать другому» - подсказка в том, что он не полагается на локальное состояние, возможно, тип возвращаемого значения находится там, где он принадлежит?
AndyM

20

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

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


Думаю, он в основном имеет в виду частные методы
Джордж Мауэр

@Ray - Верно, это применимо только к не-частным участникам. Я обновил свой ответ, чтобы отразить это.
Майкл

Точно мои мысли - просто потому, что вы можете сделать что-то статичное, не означает, что вы должны или должны ...
marc_s

Итак, что бы вы сделали для частных методов, которые можно было бы сделать статическими?
Рэй

@Ray - Вероятно, оставьте как есть, пока у меня не будет достаточно веских причин для перехода в статический режим.
Майкл

13

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


11

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


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

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

8

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


6

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

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

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

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


1
Статический метод все еще может иметь доступ к состоянию. Он просто получает состояние от переданного ему объекта. И наоборот, поля экземпляра не обязательно содержат изменяемое состояние.
Йорген Фог

6

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


3
Это технически верно, но не в реальном материальном смысле. Разница между static / non будет очень и очень редко влиять на производительность.
Foredecker

22
-1: Преждевременная оптимизация учебников. Скорость, конечно, не должна быть первым критерием при выборе статического или нестатического режима в общем случае.
Не уверен,

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

5
Я считаю, что скорость - одна из самых плохих причин, по которым вы можете решить, является ли функция статической или нестатической в ​​99% случаев. Когда дело доходит до объектно-ориентированного дизайна, есть гораздо более важные соображения, о которых подробно говорится в других публикациях.
Not Sure,

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

5

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

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

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

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


4

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

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

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


4

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


2

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


1
Вы можете изменить настройки ReSharper: P
Бернхард Хофманн,

1
Если бы это было так просто, у нас не было бы проблем от Resharper ... никогда :)
Prankster

1

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


Да, но если когда-нибудь вам понадобится это сделать, вы всегда можете сделать это не статичным. Или я что-то упускаю?
Рэй

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

Все сайты вызовов должны быть изменены со статического вызова метода на вызов функции-члена.
Брайан Энсинк,

Извините, вы добавили это после моего комментария. На мой взгляд, я думал о частных методах, но это справедливо для публичных методов.
Рэй

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

1

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


1

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

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

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

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

Еще один хороший пример - Reverse()метод на C #.
Это статический метод в Arrayклассе. Он меняет порядок вашего массива.

Код:

public static void Reverse(Array array)

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


Математика - плохой пример. Думаю, лучше: newnumber = number.round (2), чем newnumber = Math.round (number)
graffic

3
Класс Math - прекрасный пример использования статических классов. Это то, о чем эта тема, а не о том, как вы предпочитаете округлять числа ...
KdgDev

1

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

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

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

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


1

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

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

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


1

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

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


1

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

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

Я звоню в свой банк и спрашиваю их почтовый адрес.
Они спрашивают номер моего счета.
Какого черта? Неудача - должен был быть статический метод.


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

0

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


-1

В таких случаях я стараюсь перенести метод в статическую библиотеку или библиотеку utils, поэтому я не смешиваю концепцию «объекта» с концепцией «класса».

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.