C# – Should Utility Base Classes Be Avoided?

cinheritance

Knowing that C# doesn't support multiple inheritance, is it considered bad form to write a utility base class?

Some initial thoughts:

  • I could create an interface and a concretion, but then the implementation isn't portable
  • Should the developer need to extend the class in say, a decorator pattern, they could implement this new class and inherit the base class in their new class

EDIT:

N.B. I'm not talking about vanilla inheritance here e.g. poodle<–dog<–mammal<–animal

More this sort of thing (lifted from here):

    using log4net;
    using log4net.Config;

    public class LogTest2
    {
        private static readonly ILog logger = 
              LogManager.GetLogger(typeof(LogTest2));

    static LogTest2()
    {
        DOMConfigurator.Configure();
    }

    static void Main(string[] args)
    {
        logger.Debug("Here is a debug log.");
        logger.Info("... and an Info log.");
        logger.Warn("... and a warning.");
        logger.Error("... and an error.");
        logger.Fatal("... and a fatal error.");
    }
}

If I were to drop this into say, a WCF service, it would be expedient for the private member variable, constructor and perhaps some wrapper methods to sit in a base class to save cluttering up the service code (and make it reusable).

So far, so dull.

However:

What if I wanted to add some other sort of logging not supported by log4net? E.g. Acme Corp provide some class to iMessage the support team if an issue occurs.

Base class

Had I implemented the log4net stuff in a base class, I'd then have to create some new master base class that supports both classes and inherit this.

Interface

I could implement an interface but the concretion would still be in the service code which we're trying to avoid. Acme Corp's class can of course now drop straight in but we're implementing two sets of code which do very similar things in different ways.

Best Answer

I think you are on the road to a very often seen form of wrong use of inheritance. If you want a class X which uses an exchangeable type of logger, inject an object of type ILog by passing it as a constructor parameter. If your logger needs specific initialization, create a specific logger, inherited from ILog. Don't bury the logger initialization in some kind of artifical base class A of X, in attempt to make this reusable. The latter would actually work against reusability (and testability) of X, and also against the reusability of your specific logger outside of the context of X.

Related Topic