Метод можно сделать статическим, но стоит ли?

Resharper любит указывать на несколько функций в asp.net страница, которую можно сделать статической. Поможет ли мне, если я сделаю их статичными? Должен ли я сделать их статическими и переместить их в служебный класс?

13 ответов


статические методы против методов экземпляра
10.2.5 статические и экземплярные члены спецификации языка C# объясняет разницу. Как правило, статические методы могут обеспечить очень небольшое повышение производительности по сравнению с методами экземпляра, но только в несколько экстремальных ситуациях (см. ответ для более подробной информации об этом).

правило CA1822 в состояниях анализа FxCop или кода:

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

Служебный Класс
Вы не должны перемещать их в утилиту класс, если это не имеет смысла в вашем дизайне. Если статический метод относится к определенному типу, например ToRadians(double degrees) метод относится к классу, представляющему углы, имеет смысл, чтобы этот метод существовал как статический член этого типа (обратите внимание, что это запутанный пример для целей демонстрации).


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

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


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


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

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

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

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


Это интересно читать:

http://thecuttingledge.com/?p=57

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

но вот что говорит resharper documentaion: http://confluence.jetbrains.net/display/ReSharper/Member + can + be + made + static


просто добавить к @Jason True в ответ, важно понимать, что просто установка "статического" метода не гарантирует, что метод будет "чистым". Он будет апатридом в отношении класса, в котором он объявлен, но он вполне может получить доступ к другим "статическим" объектам, которые имеют состояние (конфигурация приложения и т. д.), это не всегда плохо, но одна из причин, почему я лично предпочитаю статические методы, когда я могу, что если они чисты, вы можете испытайте и рассуждайте о них в изоляции, не беспокоясь об окружающем состоянии.


вы должны делать то, что наиболее читаемо и интуитивно понятно в данном сценарии.

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


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

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


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


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


сделать статический метод означает, что вы можете вызвать метод вне класса без создания экземпляра этого класса. Это полезно при работе со сторонними объектами поставщиком или дополнений. Представьте, что вам нужно сначала создать консольный объект " con " перед вызовом con.Writeline();


Он помогает контролировать загрязнение пространства имен.


Just my tuppence: добавление всех общих статических методов в класс утилиты позволяет добавить

using static className; 

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

Я понятия не имею, является ли это хорошей практикой или нет. Мне так много нужно узнать о C# 4/5 и так много устаревшего кода для рефакторинга, что я просто пытаюсь позволить советам Roselyn направлять меня.

Джой