What is good practice when inheriting static classes isn’t possible/allowed

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

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.

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

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

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

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.

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa
Thiết kế website Thiết kế website Thiết kế website Cách kháng tài khoản quảng cáo Mua bán Fanpage Facebook Dịch vụ SEO Tổ chức sinh nhật