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

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

Пример:

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 () статическими? Пожалуйста, без отзывов, у меня есть свое мнение.

возможный дубликат Метод можно сделать статическим, но нужно ли?

drzaus 06.08.2015 20:02
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
218
1
97 790
8
Перейти к ответу Данный вопрос помечен как решенный

Ответы 8

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

Как это связано с преимуществом в производительности или памяти во время выполнения?

Scott Dorman 25.09.2008 22:27

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

Kent Boogaart 25.09.2008 22:33

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

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

Scott Dorman 25.09.2008 22:26

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

Joel Coehoorn 25.09.2008 22:32

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

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

Ответ принят как подходящий

Из Страница правил FxCop по этому поводу:

After you mark the methods as static, the compiler will emit non-virtual call sites to these members. Emitting non-virtual call sites will prevent a check at runtime for each call that ensures that the current object pointer is non-null. This can result in a measurable performance gain for performance-sensitive code. In some cases, the failure to access the current object instance represents a correctness issue.

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

frandevel 30.04.2014 11:29

Я бы даже сказал: «Если методу не нужен доступ к состоянию (this), сделайте его статическим» в качестве общего правила.

DanMan 04.03.2015 17:09

В интересах баланса стоит отметить, что многие люди в целом против статических методов, потому что они нарушают полиморфизм и означают, что объект не может быть заглушен для тестирования. например см. googletesting.blogspot.co.uk/2008/12/…

Andy 16.07.2015 13:22

@ Энди - Хорошее замечание. Один из способов провести черту - это посмотреть, получает ли статический метод доступ к чему-либо за пределами переданных вами параметров. Пока он самодостаточен таким образом, его должно быть легко протестировать, и в этом нет необходимости что-нибудь заглушить.

Neil 18.03.2016 20:45

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

Curtis Yallop 11.01.2017 01:59

Одним из положительных побочных эффектов является предупреждение компилятора (и IDE) при попытке доступа / изменения состояния за пределами вашей неизменяемой функции. Для небольших и невинных функций это может быть не так полезно, но когда все становится более сложным, это может спасти жизнь. В настоящее время с возрастающей сложностью языков программирования наличие кого-то присматривать за вами, по крайней мере лично, является большим плюсом :)

Michael Kargl 20.05.2020 12:32

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

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

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

Возьмем этот пример:

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

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

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

Вид объявления константного метода в C++, не так ли?

anhoppe 18.03.2016 16:37

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

Neil 18.03.2016 20:37

Это не обязательно правда. Предположим, что у Library есть поле экземпляра List<Book> _books для хранения его книг (не так, как вы бы разработали класс Library, вероятно, но w / e), и он передает этот список в findBook, и этот статический метод вызывает books.Clear() или books.Reverse() и т. д. Если вы предоставите статическому методу доступ к ссылке на какое-то изменяемое состояние, то этот статический метод вполне может испортить ваше состояние.

sara 19.05.2016 10:07

Правда. И в этом случае подпись покажет нам, что этот метод имеет доступ (и возможность изменять) экземпляр библиотеки.

Neil 20.05.2016 23:36

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

Neil 20.05.2016 23:42

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

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

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

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 #, позволяют извлекать класс из набора частных статических методов несколькими нажатиями клавиш. Попробуйте сделать это, когда все частные вспомогательные методы тесно связаны с полем экземпляра, и вы увидите, что это может стать настоящей головной болью.

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

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

Servy 12.10.2016 18:21

Другие вопросы по теме