7

I am developing a project in C# and due to a design decision it is not possible to have a static class inherit another static class. But I have, in my opinion, a case where this would make sense.

I have a music player which is able to play music from many different music sources: local files, YouTube, SoundCloud, Jamendo, etc. I have currently one static class for each of these sources with static methods such as retrieving the top tracks, searching for tracks, etc.

Naturally, a lot of code is shared among all these classes so I wanted to refactor and put all common code into a more generic MusicSource class. But C# doesn't allow me to do that.

What would be the best practice here? I want to get rid of all my redundant code and make it easier to create new music sources.

2
  • 4
    Given that you have countless static classes already.. why are you now considering inheritance? Why not just add a another common static class and call that from the others? Jul 12, 2013 at 8:41
  • 2
    Why do you think you need inheritance? Why can't you group the redundant code into a static class and call it from your Music Source static classes? Jul 12, 2013 at 13:23

5 Answers 5

17

Those "music source" classes sound more like non-static classes which you happen to only want one instance of. They are two different things!

Here are some reasons why you might want to make them non-static:

  • If they have (or might eventually have) some internal state. e.g. Cached login credentials, or cached lists of the top 10 tracks. Stateful static classes are a bad idea! They are basically a poor implementation of a singleton.
  • If you're going to have a lot of music sources, you may well want to perform some actions on all of them. e.g. Find a particular track from any source. With static classes you're going to need a line for each class. If you've got non-static classes you can just loop over a collection of them.

There's a great answer here which gives more reasons and goes into more detail.

3

It is not possible to inherit static classes at all (at least in C#), regardless of any 'design decision'.

Perhaps your question needs rephrasing, but can you not use non-static classes like in this contrived and overly simple example;

abstract class MusicSource 
{  
    abstract MusicData LoadMusic(string source);

    protected string SomeCommonProperty { get; set; }
}

class JamendoSource : MusicSource 
{   
    override MusicData LoadMusic(string source)
    {
        // Jamendo-specific code
    }
}
2
  • By "design decision" I was referring to the decision by Mads Torgersen. Jul 18, 2013 at 5:27
  • There's nothing todo whith his decisions. .NET does not support static inheritance... Jul 18, 2013 at 6:07
1

Using static in this case is completely wrong. People tend to use static's way to often! Basicly you have 1 "MusicPlayer" with X-amount of implementation (youtube, ...) So the first thing that should pop up in your head is inheritance.

They will all do the same, but abit different => Inheritance. You want your application to work with several kinds of sources, without any need to adapt the application itself => Inheritance/Interface segregation.

Static classes can be useful, but in this case I have a feeling that the Music classes are the core of your application... Don't build your core functionality in static classes, since you remove: testability, maintainability, reusability, extensibility, ...

You say:

I want to get rid of all my redundant code and make it easier to create new music sources.

Here again, inheritance is central...

In C#, whenever u use static classes forget about inheritance. The other way around, whenever u need inheritance, forget about static classes.

Why did you initially make them static anyway?

If you want to have only one instance available, make it a singleton. If not, just make it non-static!

9
  • The reason why I made it static was because I want to access the class from anywhere and everywhere without having to pass around the object to every constructor. Also, I only had a single source from the beginning so that's why inheritance was not obvious for me at the time I created the first class. Jul 18, 2013 at 5:25
  • 1
    Thats why thinking about what u might need in the future is a good thing. "Do I want to support new sources in the future?". You say: "The reason why I made it static was because I want to access the class from anywhere and everywhere without having to pass around the object to every constructor" That is such a bad habit. It leads to extremely poor coding. In OOP u are supposed to pass around objects in this case. Static classes helps u to avoid this passing around, but breaks all the rest. Remove the statics, thats the first thing I advice u. PS:Statics can be good, but they're often misused. Jul 18, 2013 at 6:06
  • Well I do plan on moving the classes over to a plugin system which would make them objects with inheritance. But I still don't see the benefits of not using static in this case. Passing around objects seems a lot messier as I need to change constructor and line of code creating the object, whenever I want to give a new object access to the class. Combined with the fact that only a single instance would be needed of the class, it seems more logical to use a static class. OOP principles be damned if breaking them is the more pragmatic approach. Jul 18, 2013 at 7:00
  • 1
    Have u read the link Baqueta provided in his answer: stackoverflow.com/questions/241339/… ? It has a great set f-of answers! Passing around objects and creating instances should NOT be an issue when developing .NET applications. That "way" of thinking conflicts with the OOP way of working. Jul 18, 2013 at 7:09
  • Yes, and only the point about testing caught my eye. The rest either don't apply or are avoidable with relative ease. But as I said, in this specific case it seems the best move is to move away from static classes and into a plugin system where each source is an instance of a plugin. But I'll still keep my static utility class. :) Jul 18, 2013 at 7:22
1

I am not sure if someone is still interested in this topic but shorty i tried the following. Probably it is one way for a generic solution which involved some static behavior.

  public abstract class StructureItem {
        public int index = 0;
    }

    public abstract class StructureItem<T> : StructureItem where T : StructureItem
    {
        public static List<T> Elements = new List<T>();
    }

    public class TEST1 : StructureItem<TEST1>
    {
        public TEST1()
        {
            StructureItem a = this;
            this.index = 1;
            TEST1.Elements.Add(this);
        }
    }

    public class TEST2 : StructureItem<TEST2>
    {
        public TEST2()
        {
            StructureItem a = this;
            this.index = 2;
            TEST2.Elements.Add(this);
        }
    }

    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();

            var test1 = new TEST1();
            var test2 = new TEST2();

            List<StructureItem> aList = new List<StructureItem>();

            aList.Add(test1);
            aList.Add(test2);

            Console.WriteLine("all Elements:");
            foreach (var item in aList)
            {
                Console.WriteLine("Element " + item.index);
            }
            Console.WriteLine("TEST1 Elements:");
            foreach (var item in TEST1.Elements)
            {
                Console.WriteLine("Element "+item.index);
            }
            Console.WriteLine("TEST2 Elements:");
            foreach (var item in TEST2.Elements)
            {
                Console.WriteLine("Element " + item.index);
            }

        }
    }

Output:

all Elements:
Element 1
Element 2
TEST1 Elements:
Element 1
TEST1 Elements:
Element 2
0

I am very late to this party but will add an approach I often use in case it helps anyone in the future: The OOP principle of "composition over inheritance".

If I have multiple static classes that replicate functionality, I will often abstract the shared functionality into an instance class and then instantiate an object of that class inside each of the static classes. Then the static classes can use and expose certain aspects of the contained instance class as needed.

For example, if I have two static classes that share functions FunctionA() and FunctionB() but not, say, functions FunctionC() and FunctionD() like below...

public static class Foo
{
    public static void FunctionA()
    {
        /* Shared */
    }

    public static void FunctionB()
    {
        /* Shared */
    }

    public static void FunctionC()
    {
        /* Not shared */
    }
}

public static class Bar
{
    public static void FunctionA()
    {
        /* Shared */
    }

    public static void FunctionB()
    {
        /* Shared */
    }

    public static void FunctionD()
    {
        /* Not shared */
    }
}

...then I will abstract FunctionA() and FunctionB() into a shared instance class, create instances of it in each static class, and expose the shared functionality like below...

public class Shared
{
    public void FunctionA()
    {
        /* Shared */
    }

    public void FunctionB()
    {
        /* Shared */
    }
}

public static class Foo
{
    private static Shared shared = new Shared();

    public static void FunctionA()
    {
        shared.FunctionA();
    }

    public static void FunctionB()
    {
        shared.FunctionB();
    }

    public static void FunctionC()
    {
        /* Not shared */
    }
}

public static class Bar
{
    private static Shared shared = new Shared();

    public static void FunctionA()
    {
        shared.FunctionA();
    }

    public static void FunctionB()
    {
        shared.FunctionB();
    }

    public static void FunctionD()
    {
        /* Not shared */
    }
}

I'd be curious if others could critique of this approach, I'd love to learn about any pitfalls.

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