Well, in the case of String.Empty
it is more of a constant (kind of like Math.PI
or Math.E
) and is defined for that type. Creating a sub-class for one specific value is typically bad.
On to your other (main) question as to how they are "inconvenient:"
I've only found static properties and methods to be inconvenient when they are abused to create a more functional solution instead of the object-oriented approach that is meant with C#.
Most of my static members are either constants like above or factory-like methods (like Int.TryParse
).
If the class has a lot of static properties or methods that are used to define the "object" that is represented by the class, I would say that is typically bad design.
One major thing that does bother me with the static methods/properties is that you sometimes they are too tied to one way of doing something without providing an easy way to create an instance the provides with easy overrides to the behavior. For example, imagine that you want to do your mathematical computations in degrees instead of radians. Since Math
is all static, you can't do that and instead have to convert each time. If Math
were instance-based, you could create a new Math
object that defaulted to radians or degrees as you wished and could still have a static property for the typical behaviors.
For example, I wish I could say this:
Math mD = new Math(AngleMode.Degrees); // ooooh, use one with degrees instead
double x = mD.Sin(angleInDegrees);
but instead I have to write this:
double x = Math.Sin(angleInDegrees * Math.PI / 180);
(of course, you can write extension methods and constants for the conversions, but you get my point).
This may not be the best example, but I hope it conveys the problem of not being able to use the methods with variations on the default. It creates a functional construct and breaks with the usual object-oriented approach.
(As a side note, in this example, I would have a static property for each mode. That in my eyes would be a decent use of the static properties).