"Which one is better?" is a question that largely depends on specific scenario. In some cases you may want static methods, in other cases instance methods, sometimes both. Rather than trying to provide an absolute edict, here are some of my thoughts on how to make this decision.
Clarity Considerations
Static methods can be used when it would be awkward to use an instance of an object. For example, the .NET string class has String.Concat( ) which can concatenate multiple strings.
It is clear to have: String.Concat( "A", "B" );
It's awkward to have: "A".Concat( "B" );
Sometimes it is clearer to provide a name for an operation rather than encoding it as a constructor overload. Int.Parse( ) is a good example. Int could have a constructor that takes a string, but it is unclear what the intent is. The static Parse() method adds clarity.
Maintainability Considerations
Sometimes you have no choice but to implement a function as a static utility method. It may be impossible to add new methods to the class - you may not have the source code, you may wish to avoid testing impacts, etc.
Even when you can add an instance method, it may be useful to de-clutter a class by implementing infrequent or special-purpose methods in utility classes. You should only do this, however, when you can implement the utility class using only the public interface of the type you are extending. In C# 3.5 you can use extension methods to create the illusion that the utility methods are instance methods of the class.
Polymorphism Considerations
If a function is likely to be overridden in a derived type, you should make it an instance member and mark it with the virtual keyword. Instance methods not marked virtual are no more extensible than static methods.
Best Practice Considerations
Static functions should (generally) have no side effects. In other words, they should not modify the state of either of their parameters. Functions that have side effects are best implemented as instance methods of an object.
In OOP there is the single responsibility principle (SRP), which basically states that "every class should only have one reason to change." If adding an instance method to a particular class would violate the SRP, consider factoring that logic out of the class.
Usability Considerations
Sometimes a design goal of your code (particularly framework level code) is usability. In such cases it may be useful to provide both an instance and a static version of a function. However, in such cases it is highly advisable that the instance version be implemented as a call to the static version. This approach allows the consumer of the class to decide which makes sense. An example of this approach is the string.Compare()
and string.CompareTo()
methods - the former is static while the later is an instance method. This allows the string class to conform to a particular interface (IComparable) while also providing a nice syntax: string.Compare( "A", "a" )
.