Преимущества использования частных статических методов

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

Пример:

foreach (XmlElement element in xmlDoc.DocumentElement.SelectNodes("sample")) { string first = GetInnerXml(element, ".//first"); string second = GetInnerXml(element, ".//second"); string third = GetInnerXml(element, ".//third"); } 

 private static string GetInnerXml(XmlElement element, string nodeName) { return GetInnerXml(element, nodeName, null); } private static string GetInnerXml(XmlElement element, string nodeName, string defaultValue) { XmlNode node = element.SelectSingleNode(nodeName); return node == null ? defaultValue : node.InnerXml; } 

Есть ли какое-либо преимущество в объявлении методов GetInnerXml () как статических? Никаких мнений, пожалуйста, у меня есть мнение.

На странице правил FxCop :

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

Когда я пишу class, большинство методов делятся на две категории:

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

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

Возьмем следующий пример:

  библиотека открытого classа
 {
     private static Book findBook (Список <Книга> книги, название строки)
     {
         // код идет здесь
     }
 } 

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

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

Вызов статического метода генерирует инструкцию вызова на промежуточном языке Microsoft (MSIL), тогда как вызов метода экземпляра генерирует команду callvirt, которая также проверяет ссылки на нулевые объекты. Однако большую часть времени разница в производительности между этими двумя значениями невелика.

src: MSDN – http://msdn.microsoft.com/en-us/library/79b3xss3(v=vs.110).aspx

Да, компилятору не нужно передавать неявный this указатель на static методы. Даже если вы не используете его в своем методе экземпляра, он все равно передается.

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

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

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

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

 public class MyClass { private readonly MyDependency _dependency; public MyClass(MyDependency dependency) { _dependency = dependency; } public int CalculateHardStuff() { var intermediate = StepOne(_dependency); return StepTwo(intermediate); } private static int StepOne(MyDependency dependency) { return dependency.GetFirst3Primes().Sum(); } private static int StepTwo(int intermediate) { return (intermediate + 5)/4; } } public class MyDependency { public IEnumerable GetFirst3Primes() { yield return 2; yield return 3; yield return 5; } } 

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

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

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

Как уже было сказано, существует множество преимуществ для статических методов. Однако; имейте в виду, что они будут жить в куче для жизни приложения. Недавно я провел день, отслеживая утечку памяти в службе Windows … утечка была вызвана частными статическими методами внутри classа, который реализовал IDisposable и последовательно вызывался из инструкции using. Каждый раз, когда этот class был создан, память была зарезервирована в куче для статических методов в classе, к сожалению, когда class был удален, память для статических методов не была выпущена. Это привело к тому, что память этой службы памяти потребляла доступную память сервера в течение нескольких дней с outlookируемыми результатами.

Давайте будем гением компьютера.