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





Да, компилятору не нужно передавать неявный указатель this методам static. Даже если вы не используете его в своем методе экземпляра, он все равно передается.
Как это связано с преимуществом в производительности или памяти во время выполнения?
Передача дополнительного параметра означает, что ЦП должен выполнить дополнительную работу, чтобы поместить этот параметр в регистр и поместить его в стек, если метод экземпляра вызывает другой метод.
Это заставляет вас не забывать также объявлять любые члены в области класса, которые функция использует, как статические, что должно сэкономить память для создания этих элементов для каждого экземпляра.
Просто потому, что это переменная в области класса, не означает, что она должна быть статической.
Нет, но если он используется статическим методом, тогда ДОЛЖЕН будет статическим. Если бы метод не был статическим, вы, возможно, не сделали бы член класса статическим, и это привело бы к увеличению памяти, используемой для каждого экземпляра класса.
Это будет немного быстрее, так как этот параметр не передается (хотя стоимость вызова метода, вероятно, значительно превышает эту экономию).
Я бы сказал, что лучшая причина, по которой я могу думать о частных статических методах, заключается в том, что это означает, что вы не можете случайно изменить объект (поскольку этого указателя нет).
Из Страница правил 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.
Я бы также добавил, что «статическое» предложение не вредит и уже предоставляет некоторую «документацию» с одним словом. Он сообщает вам, что этот метод не использует ни одного члена экземпляра, и вы получаете эту документацию почти бесплатно.
Я бы даже сказал: «Если методу не нужен доступ к состоянию (this), сделайте его статическим» в качестве общего правила.
В интересах баланса стоит отметить, что многие люди в целом против статических методов, потому что они нарушают полиморфизм и означают, что объект не может быть заглушен для тестирования. например см. googletesting.blogspot.co.uk/2008/12/…
@ Энди - Хорошее замечание. Один из способов провести черту - это посмотреть, получает ли статический метод доступ к чему-либо за пределами переданных вами параметров. Пока он самодостаточен таким образом, его должно быть легко протестировать, и в этом нет необходимости что-нибудь заглушить.
Многие разработчики не знакомы с «приватной статикой». Я использовал его в общей кодовой базе моей команды, и это привело к путанице. В свою очередь, это дает очень незначительную выгоду. Мы могли бы обучить всех в команде, включая всех будущих разработчиков, поддерживающих код, тому, что это означает. Но преимущество переключения частного метода в частный статический настолько незначительно (т.е. устраняет зависимость от данных экземпляра), что не стоит усилий и путаницы. В любом случае метод уже является частным. Это языковая причуда, которую на самом деле не нужно знать.
Одним из положительных побочных эффектов является предупреждение компилятора (и IDE) при попытке доступа / изменения состояния за пределами вашей неизменяемой функции. Для небольших и невинных функций это может быть не так полезно, но когда все становится более сложным, это может спасти жизнь. В настоящее время с возрастающей сложностью языков программирования наличие кого-то присматривать за вами, по крайней мере лично, является большим плюсом :)
Когда я пишу класс, большинство методов делятся на две категории:
Статические методы полезны, потому что, просто взглянув на его подпись, вы знаете, что при вызове он не использует и не изменяет состояние текущего экземпляра.
Возьмем этот пример:
public class Library
{
private static Book findBook(List<Book> books, string title)
{
// code goes here
}
}Если экземпляр состояния библиотеки когда-либо будет облажаться, и я пытаюсь выяснить, почему, я могу исключить findBook как виновника только на основании его подписи.
Я стараюсь как можно больше общаться с помощью сигнатуры метода или функции, и это отличный способ сделать это.
Вид объявления константного метода в C++, не так ли?
Да - это еще один хороший способ использовать язык для упрощения вещей за счет ограничения того, что может пойти не так.
Это не обязательно правда. Предположим, что у Library есть поле экземпляра List<Book> _books для хранения его книг (не так, как вы бы разработали класс Library, вероятно, но w / e), и он передает этот список в findBook, и этот статический метод вызывает books.Clear() или books.Reverse() и т. д. Если вы предоставите статическому методу доступ к ссылке на какое-то изменяемое состояние, то этот статический метод вполне может испортить ваше состояние.
Правда. И в этом случае подпись покажет нам, что этот метод имеет доступ (и возможность изменять) экземпляр библиотеки.
Практически любую защитную конструкцию, которую мы можем использовать, есть способ подорвать ее. Но их использование по-прежнему разумно и помогает подтолкнуть нас в правильном направлении, к «яме успеха».
Вызов статического метода генерирует инструкцию вызова на промежуточном языке 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. Каждый раз, когда этот класс создавался, память в куче резервировалась для статических методов внутри класса, к сожалению, когда класс был удален, память для статических методов не высвобождалась. Это привело к тому, что объем памяти этой службы потребовал доступную память сервера в течение нескольких дней с предсказуемыми результатами.
В этом нет никакого смысла. В куче никогда хранится память для кода для методов Любые, статических или иных. Куча предназначена для экземпляров объектов. В стеке будут данные для любого вызова любого метода (для хранения памяти для параметров, возвращаемого значения, не поднимаемых локальных переменных и т. д.), Но все это исчезает, когда метод завершает выполнение.
возможный дубликат Метод можно сделать статическим, но нужно ли?