2008-09-25 3 views
160

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

Пример:

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) как статические? Никаких мнений, пожалуйста, у меня есть мнение.

+0

Возможный дубликат [Метод может быть сделан статическим, но должен ли он?] (Http://stackoverflow.com/questions/169378/method-can-be-made-static-but-should-it) – drzaus 2015-08-06 17:02:55

ответ

174

С FxCop rule page на это:

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

+21

Я бы также добавил, что «статическое» предложение не наносит вреда и предоставляет уже некоторую «документацию» с 1 словом. Он сообщает вам, что этот метод не использует какой-либо экземплярный элемент, и вы получаете эту документацию почти бесплатно – frandevel 2014-04-30 07:29:05

+8

. Я бы сказал, что: «Если для метода не нужен доступ к состоянию (это), сделайте его« static »as общее правило. – DanMan 2015-03-04 14:09:49

12

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

+0

Как сделать это связано с преимуществом производительности или памяти во время выполнения? – 2008-09-25 18:27:57

+8

Передача дополнительного параметра означает, что ЦП должен выполнить дополнительную работу, чтобы поместить этот параметр в регистр и вставить его в стек, если метод экземпляра обращается к другому методу. – 2008-09-25 18:33:49

4

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

+0

Просто потому, что это переменная класса, не означает, что она должна быть статичной. – 2008-09-25 18:26:14

+2

Нет, но если он используется статическим методом, то он _MUST_ будет статичным. Если метод не был статическим, возможно, вы не сделали статический член класса, и это приведет к увеличению объема памяти, используемого для каждого экземпляра класса. – 2008-09-25 18:32:05

5

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

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

71

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

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

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

Возьмем такой пример:

public class Library 
{ 
    private static Book findBook(List<Book> books, string title) 
    { 
     // code goes here 
    } 
}

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

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

60

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

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

1

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

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<int> GetFirst3Primes() 
    { 
     yield return 2; 
     yield return 3; 
     yield return 5; 
    } 
} 

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

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

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

-2

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

Смежные вопросы