2

I've recently caught an odd behaviour in my own coding: At some point in the last year I began creating protected static methods to implement the logic of my public methods, ensuring that the protected static version contains all of the logic, but is not affected by state.

e.g.

class Demo
{
    string someAttribute;
    public Demo(string someAttribute)
    {
        this.someAttribute = someAttribute;
    }

    // public method only calls the static method, passing all 
    // parameters sent to the public function as well as any 
    // of the object's attributes required by the function.
    public string AppendSomeAttribute(string textToAppendTo) =>
        AppendSomeAttribute(textToAppendTo, someAttribute);

    // static method is not publicly exposed.  It contains all 
    // of the function's logic, but is not affected by state
    protected static string AppendSomeAttribute(string textToAppendTo, string someAttribute) =>
        string.Concat(textToAppendTo, someAttribute);

    /*
    // this is what a normal person would do:
    public string AppendSomeAttribute(string textToAppendTo) =>
        string.Concat(textToAppendTo, someAttribute);
    */
}

I can't recall reading anything that would have triggered this change. My best guess is I read something advising it which stuck in my subconscious; but it may just be a bad habit I'd unconsciously picked up.

Trying to work out why this may be advised I came up with the following:

  • All logic is handled in a single place; so where there are multiple public methods taking different parameters this helps keep all logic in one routine (definitely makes sense where the version of that routine which supplies all parameters is not supposed to be publicly exposed; otherwise I can't see a benefit).
  • By removing the object's state from the equation the logic of these methods is more easily tested / proven; either by unit tests, or when copy-pasting code to LinqPad (or similar) to try it out in a sandbox.

However, those aren't great justifications for doing this as a de-facto coding style (i.e. where there isn't a specific scenario to justify this, such as the many public overloads of the same method with none taking all parameters example, as outlined above).

Question:

Is there any clear benefit to writing code in this way?

2
  • 1
    What I dislike about this style is the added level of indirection. It's unnecessary and makes it harder to read the code.
    – 17 of 26
    Commented Apr 19, 2018 at 15:03
  • 3
    You say "ensuring that the protected static version ... is not affected by state" -- but static methods have access to all the state of an instance; your technique only "works" because (1) you don't pass in any instance, and (2) no instance is available statically. So your technique only works because you have imposed a discipline on your static methods. If you're good at imposing discipline, then why do you need the technique in the first place? I really don't see what problem you're trying to solve. Commented Apr 19, 2018 at 21:45

4 Answers 4

2

This would be OK, provided you do have descendants that meaningfully share that logic.

The thing with protected is that it sends a message, it raises expectations. And all too often, after some digging, I find no descendants are using those protected members and it appears it was just a matter of "just in case I will need to access this later from a hypothetical future descendant" (that never saw the light of day). This is not good.

Any use of protected should fit the inheritance model in the sense that it clearly represents common logic for all child classes. Then it makes sense and helps the reader understand the application.

5
  • just in case I will need to access this There is an argument to be made either way. Making things private unless needed in a derived class allows developers to change access modifiers ad hoc. This can create a bad habit of changing things based on what you need, instead of first trying to use the existing code as is. To avoid that, the inital developer can label things as protected/private based on which is the most appropriate. I'd expect the initial developer (of the base class) to be more knowledgeable to make an informed decision here, compared to the later developer (of a subclass).
    – Flater
    Commented Apr 20, 2018 at 11:33
  • @Flater "the inital developer can label things as protected/private based on which is the most appropriate" Yes, that is what the initial developer should do and is exactly my point. If it is private, it signals that it is not supposed to be used by descendants. If it is protected, it invites/solicits to be used by descendants. This means it should be a conscious decision on a case-by-case basis rather than a habit. Any next developer has the ability to change things around anyway, the goal here is to make them "fall into the pit of success" by choosing appropriate access specifiers. Commented Apr 20, 2018 at 12:34
  • Your answer seems to argue the opposite: "The thing with protected is that it sends a message, it raises expectations. And all too often, after some digging, I find no descendants are using those protected members" In your comment, you say that " If it is protected, it invites/solicits to be used by descendants." But your answer doesn't account for the time between designing a base class and creating a derived class that actually needs to use that protected member (which is not necessarily the first derived class). It should be perfectly fine to have a protected that is not yet used.
    – Flater
    Commented Apr 20, 2018 at 12:44
  • Which means that it's not a matter of "just in case I will need to access this later from a hypothetical future descendant", but rather "a hypothetical future descendant would be allowed to access this member". If you agree with the former, then you are implicitly saying that everything should be private by default (thus leaving it up to the second developer to change the access modifier when he wants to, possibly without looking for another way to achieve his goal).
    – Flater
    Commented Apr 20, 2018 at 12:48
  • There is no disagreement between us. If protected makes sense, by all means, make it protected. The "just in case" implies you do not really know why it should be protected. That is what I am warning against. Commented Apr 20, 2018 at 13:26
3

protected static methods are an odd thing to create. I suspect you mean to create private static methods. Being protected, your comment "static method is not publicly exposed" isn't 100% correct. It can be accessed via child class as shown below:

using System;

public class Program
{
    static void Main()
    {
        var x = new Demo2();
        Console.WriteLine(x.AppendSomeAttribute("We hacked it. ")); 
        // Prints "We hacked it. lol" 
    }
}

class Demo
{
    private string _someAttribute;
    public Demo(string someAttribute) => _someAttribute = someAttribute;

    public string AppendSomeAttribute(string textToAppendTo) =>
        AppendSomeAttribute(textToAppendTo, _someAttribute);

    protected static string AppendSomeAttribute(string txtToAppendTo, string someAttrbute) =>
        string.Concat(txtToAppendTo, someAttrbute);
}

class Demo2 : Demo
{
    public Demo2() : base("lol") {}

    public static string LetsHack(string textToAppendTo, string someAttribute) =>
        AppendSomeAttribute(textToAppendTo, someAttribute);
}

You can see in action, here.

Private helper methods are a common pattern. Marking them as static when they do not access the object's state is also a common pattern. protected static is just plain weird though and I'm sure this is the first time I've ever seen anyone use it.

1
  • Thanks for the feedback. Agreed that the accessibility level makes these available to subclasses. My question's more about whether it's a good idea to have a helper function within a class where that helper function is solely used to encapsulate the logic of a single method in the same class; i.e. as opposed to simply putting that logic in the public method itself. Apologies that my wording wasn't that clear.
    – JohnLBevan
    Commented Apr 19, 2018 at 15:12
1

This is common practice when writing multi-thread safe classes, although I would normally avoid inheritance as much as possible in such a class. If the static method is entirely pure (side effect free), it can be invoked from outside of mutex protected blocks, which is a big advantage when you are trying to avoid nested locks.

1

The main use case (according to your own explanation) is to avoid using instance values. But I see no reason to keep the method as static after it is developed.

  1. Develop a (non-static) method
  2. Put it to static to see if any errors pop up in the method body, which indicates you're using instance values.
  3. Remove the static.

I'm all for clever methods to factcheck something, but I see no reason to persist your clever-but-unusual approach after you've confirmed what you wanted to.

As a secondary argument, if you already can't keep track of the values used in a method, the method is probably handling too much to begin with.


By removing the object's state from the equation the logic of these methods is more easily tested / proven; either by unit tests,

I'm not quite following here. Static methods (by themselves) are notoriously hard to unit test because it's not easy to mock a state.

A static wrapped in a non-static is no different from an allround non-static setup; in terms of unit testing.


All logic is handled in a single place; so where there are multiple public methods taking different parameters this helps keep all logic in one routine (definitely makes sense where the version of that routine which supplies all parameters is not supposed to be publicly exposed; otherwise I can't see a benefit).

This is an argument for public/protected/private, not static/instance. You can achieve the exact same goal with protected/private instance methods.


I simply don't quite see the point of your code. Nothing changes if you remove the static keyword from your example.

In your code comments, you say that [protected] static method is not publicly exposed, which is a mislabeling. It's not publicly exposed because it is protected, regardless of whether it's static or not.

If you're talking about how a static method is not exposed on an instance; that is partially true. But that is an argument about avoiding developer error, not logical correctness.
Furthermore: a protected static is still publicly available inside its class and all classes that derive from it. It's not available as this.MyStaticMethod(), but it is still available as MyStaticMethod(). You're not completely circumventing its availability.

What you say isn't wrong, but I see no argument that justifies this additional level of abstraction.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.