250

When creating a class that has internal private methods, usually to reduce code duplication, that don't require the use of any instance fields, are there performance or memory advantages to declaring the method as static?

Example:

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;
}

Is there any advantage to declaring the GetInnerXml() methods as static? No opinion responses please, I have an opinion.

Mihai Limbășan
  • 64,368
  • 4
  • 48
  • 59
NerdFury
  • 18,876
  • 5
  • 38
  • 41
  • 1
    possible duplicate of [Method can be made static, but should it?](http://stackoverflow.com/questions/169378/method-can-be-made-static-but-should-it) – drzaus Aug 06 '15 at 17:02

8 Answers8

260

From the FxCop rule page on this:

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.

Scott Dorman
  • 42,236
  • 12
  • 79
  • 110
  • 50
    I would also add that a "static" clause does not harm and provides already some "documentation" with 1 word. It tells you that this method is not using any instance member, and you get this documentation almost for free – frandevel Apr 30 '14 at 07:29
  • 27
    I'd go as far as saying: "If a method doesn't need state access (this), make it static" as a general rule. – DanMan Mar 04 '15 at 14:09
  • 5
    In the interests of balance, it's worth pointing out that a lot of people are generally against static methods because they break polymorphism, and mean the object cannot be stubbed for testing. for example see http://googletesting.blogspot.co.uk/2008/12/static-methods-are-death-to-testability.html – Andy Jul 16 '15 at 10:22
  • 2
    @Andy--Good point. One way to draw the line would be to look at whether the static method is accessing anything outside of the parameters you pass in. As long as it is self-contained in this way, it should be easy to test, and there is no need to stub anything. – Neil Mar 18 '16 at 17:45
  • 7
    Many developers are not familiar with "private static". I have used it in my team's common code base and it has led to confusion. In return, it provides very minor benefit. We could choose to educate everyone on the team, including all future developers maintaining the code, as to what it means. But the benefit of switching a private method to a private static is so minor (ie removing dependence on the instance data), it is not worth the effort and confusion. The method is already private-scope either way. It is a language quirk that is not really necessary to know. – Curtis Yallop Jan 10 '17 at 22:59
  • One positive side effect is the compiler (and IDE) warning you when trying to access / mutate state outside of your immutable function. For small and innocent functions this might not be as useful but when things are getting more complex this might be a life saver. With increasing complexity of programming languages nowadays, having someone watch over you, at least personally, is a major plus :) – Michael Kargl May 20 '20 at 09:32
107

When I'm writing a class, most methods fall into two categories:

  • Methods that use/change the current instance's state.
  • Helper methods that don't use/change the current object's state, but help me compute values I need elsewhere.

Static methods are useful, because just by looking at its signature, you know that the calling it doesn't use or modify the current instance's state.

Take this example:

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

If an instance of library's state ever gets screwed up, and I'm trying to figure out why, I can rule out findBook as the culprit, just from its signature.

I try to communicate as much as I can with a method or function's signature, and this is an excellent way to do that.

Neil
  • 7,227
  • 5
  • 42
  • 43
  • 1
    Kind of const-method declaration in C++, isn't it? – anhoppe Mar 18 '16 at 13:37
  • Yes--that's another good way to use the language to simplify things by limiting what could go wrong. – Neil Mar 18 '16 at 17:37
  • This isn't necessarily true. Let's assume that a `Library` has an instance field `List _books` to store it's books (not how you'd design a `Library` class probably but w/e), and it passes this list to `findBook`, and that static method calls `books.Clear()` or `books.Reverse()` and so on. If you give a static method access to a reference to some mutable state, then that static method can very well mess up your state. – sara May 19 '16 at 07:07
  • 2
    True. And in that case, the signature would show us that this method had access to (and the ability to mutate) an instance of Library. – Neil May 20 '16 at 20:36
  • For virtually any protective construct we might use, there is some way to undermine it. But using them is still wise and helps nudge us in the right direction, toward the "pit of success". – Neil May 20 '16 at 20:42
85

A call to a static method generates a call instruction in Microsoft intermediate language (MSIL), whereas a call to an instance method generates a callvirt instruction, which also checks for a null object references. However, most of the time the performance difference between the two is not significant.

Source: MSDN - https://learn.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2012/79b3xss3(v=vs.110)

Pang
  • 9,564
  • 146
  • 81
  • 122
Marek Takac
  • 1,105
  • 7
  • 11
18

Yes, the compiler does not need to pass the implicit this pointer to static methods. Even if you don't use it in your instance method, it is still being passed.

Kent Boogaart
  • 175,602
  • 35
  • 392
  • 393
  • How does this relate to a performance or memory advantage at runtime? – Scott Dorman Sep 25 '08 at 18:27
  • 13
    Passing an extra parameter means the CPU has to do extra work to place that parameter in a register, and push it onto the stack if the instance method calls out to another method. – Kent Boogaart Sep 25 '08 at 18:33
6

This forces you to remember to also declare any class-scoped members the function uses as static as well, which should save the memory of creating those items for each instance.

Joel Coehoorn
  • 399,467
  • 113
  • 570
  • 794
  • Just because it's a class-scoped variable doesn't mean it should be static. – Scott Dorman Sep 25 '08 at 18:26
  • 3
    No, but if it's used by a static method then it _MUST_ be static. If the method was not static then you might not have made the class member static, and that would result in more memory used for each instance of the class. – Joel Coehoorn Sep 25 '08 at 18:32
6

It'll be slightly quicker as there is no this parameter passed (although the performance cost of calling the method is probably considerably more than this saving).

I'd say the best reason I can think of for private static methods is that it means you can't accidentally change the object (as there's no this pointer).

Free Wildebeest
  • 7,272
  • 8
  • 38
  • 42
4

I very much prefer all private methods to be static unless they really can't be. I would much prefer the following:

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;
    }
}

over every method accessing the instance field. Why is this? Because as this process of calculating becomes more complex and the class ends up with 15 private helper methods, then I REALLY want to be able to pull them out into a new class that encapsulates a subset of the steps in a semantically meaningful way.

When MyClass gets more dependencies because we need logging and also need to notify a web service (please excuse the cliche examples), then it's really helpful to easily see what methods have which dependencies.

Tools like R# lets you extract a class from a set of private static methods in a few keystrokes. Try doing it when all private helper methods are tightly coupled to the instance field and you'll see it can be quite a headache.

sara
  • 3,521
  • 14
  • 34
-4

As has already been stated, there are many advantages to static methods. However; keep in mind that they will live on the heap for the life of the application. I recently spent a day tracking down a memory leak in a Windows Service... the leak was caused by private static methods inside a class that implemented IDisposable and was consistently called from a using statement. Each time this class was created, memory was reserved on the heap for the static methods within the class, unfortunately, when the class was disposed of, the memory for the static methods was not released. This caused the memory footprint of this service to consume the available memory of the server within a couple of days with predictable results.

  • 7
    This doesn't make any sense. The heap *never* stores memory for the code for *any* methods, static or otherwise. The heap is for object instances. There will be data on the stack for any invocation of any method (to hold the memory for the parameters, return value, non-hoisted locals, etc.) but all of that goes away when the method finishes executing. – Servy Oct 12 '16 at 15:21