简体   繁体   中英

Helper methods in C#: Static or non-static?

I've got a class with some functions which realistically are just 'helper' methods that client code could do itself with other public accessor properties/methods, and I'm undecided as to whether I should define these as properties with a getter, instance methods, or static methods that take the instance as a parameter. In addition, I've also got an interface extracted from the class that is used pretty much everywhere except on construction, to allow my code to use any class implemented against the interface.

The question is, which is best from a design point of view? For example, as a means of getting the initial from this class:

class Person : IPerson {
  private string name;

  public string Name { get { return this.name; } }

  // Property with getter
  public string Initial { get { return this.name.Substring(0,1); } }

  // Instance method
  public string GetInitial { return this.name.Substring(0,1); }

  // Static method
  public static string GetInitial(IPerson person) {
    return person.Name.Substring(0,1);
  }
}

The property lends itself to shorter, more readable client code, but would require anyone implementing against IPerson to write their own implementation, as would the instance method.

The static method would mean implementing classes wouldn't need to write their own, and my code can guarantee how the initial is determined based on the name, but it means it can't be on the interface, and client code's a little more verbose.

Does it just come down to whether not it's a good idea to allow implementing classes to specify how helper methods are calculated?

EDIT: Minor aside, why won't SO let me add the best-practices tag?

How about an extension method?

namespace IPersonExtensions
{
    public static class IPersonExtensionClass
    {
        public static string Initial(this IPerson @this)
        {
            return @this.name.Substring(0, 1);
        }
    }
}

Use it like this:

string initial = person.Initial();

This way, you can share implementation without having to inherit or rewrite code. Using the separate namespace makes it possible for users to choose whether they want to use this code or not.

I go back and forth, but I've starting leaning toward making them non static .

Case for static : Forces you to declare that the function doesn't use member variables and leave it stateless. If you accidentally let state creep in by needing member variables, the compiler will warn you and you have to make a concrete decision.

Case for a member function: Static functions are hard to inherit from, so changing the behavior is difficult. Makes testing more difficult as well since it's harder to substitute that function to test something else. Say you had something that used Initial and you wanted to return something specific for a test...

As an aside (and an extreme example), some of my extensions use a IOC container to locate a concrete class and call a member on it.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM