1

I know that multiple inheritance in C# is only allowed by using Interfaces and that there are very valid reasons why multiple inheritance can quickly become a real headache. (Working in .NET Framework if that makes any difference to the answers)

However.

In working on various projects accross many classes I find myself returning to the same patterns to handle behaviour. For example I have an Interface IXMLSavable which requires the functions GetXML() and SetFromXML(XElement e) to be implemented. The way I implement this in every class is, that I write different functions for different versions of the XML (If I changed something in the GetXML() I want to maintain backwards compatibility...). And according to a version-attribute on the root Element I switch case to the right ReadVersionX(XElement e) function so all my data stays consitent.

Another example would be centered around eventing. If for example I want to implement a "stop firing events for the time being"-Lock I would go about thusly:

private bool suppressEvents;
public bool SuppressEvents
{
    get { return suppressEvents; }
    set
    {
        bool prevValue=SuppressEvents;
        suppressEvents=value;
        if(prevValue!=SuppressEvents && !SuppressEvents) TheChangeEvent?.Invoke();
    }
}

So I can run multiple operations on the object in question without it giving of a right old firework display of events. Again: This code will be almost unchanged for a lot of classes.

For the XML one I could refactor this to a class that has a Dictionary<int,delegate> ReadFunctions which I could then set in every implementation (I concede that there needs to be a bit of customisation in the "implementing" class) and reduce the amount of bolierplate for every class (the explicit switching on the version attribute) to just filling this dictionary.

The eventing one could go into a class on its own quite readily, I would probably only need to hook up the right event to the invokation, but that could easily be remedied by an abstract function I will have to implement (again: customisation still necessary but much less boilerplate).

Each "now-class-was-interface" on its own would make a splendid base class for any object. I could use functionality down an inheritance tree and customise it by overwriting functionality with new if I would need it.

The problem starts when I want to combine the two now-classes together. Due to the limitation in C# (which, again, is there for a reason) I cannot inherit from both above described classes at the same time. This would only be possible if I have one of these classes inherit from the other. Which would be possible, but would lead to a whole lot of a different headache when I want one functionality but not the other. Or the other functionality and not the one. The way around that would be to create a plethora of permutation classes (so one class for each combination of the functionaities). And while that would solve the problem it would probably be a nightmare to maintain.

So the real question is: Is there a way to correctly plug in different already implemented functionality into a class in an inheritance like manner that allows the addition of multiple distinct functionality packages as opposed to interfaces that cannot by the very nature of themselves provide any concrete implementation.

9
  • 1
    Since C# version 8 there is support for default implementation in interfaces. Hence, you can you interfaces to achieve quasi-multiple inheritance, combining several pre-defined functionalities in a single class. See also learn.microsoft.com/en-us/dotnet/csharp/language-reference/…. Commented Nov 28, 2022 at 9:01
  • Unfortunately it is not possible with .NET Framework stackoverflow.com/a/57020770/1968308 Commented Nov 28, 2022 at 9:07
  • Traits in C# using Fody. Commented Nov 28, 2022 at 9:13
  • 1
    @PanagiotisKanavos: Just because it may be out of fashion in certain domains does not mean it might not help solve a problem without much hassle. And event streaming is not a problem I am trying to solve. It is rather used for data storage, and while it may not be the best data format there is, it works for my purpose as intended. Commented Nov 28, 2022 at 9:35
  • 1
    The point is that serialization should never be baked into entities or DTOs. What if the schema changes? .NET Framework already supports customizable XML serialization through its own XML attributes and classes like XmlSerializer and DataContractSerializer. Why not use these? The question then becomes how does XmlSerializer handle versioning or how does DataContractSerializer handle versioning?. There are a lot of articles that explain how to do that, eg Data Contract Versioning Commented Nov 28, 2022 at 9:46

1 Answer 1

1

In many cases you can avoid inheritance with the use of interfaces/default interface methods/extension methods, decorators, or some other pattern.

In your case with xml you could simply change your interface to have one ReadMethod per version, and use a extension method to select the correct one

public interface IXMLReadable{
    void ReadVersion1(XElement e);
    void ReadVersion2(XElement e);
}
public static class IXMLReadableExtensions {
    public static void Read(this IXMLReadable self, XElement e){
        // Read version from xml, call ReadVersion1 or ReadVersion2
    }
}

default interface methods would do more or less the same thing, with the added advantage of allowing the class to override the Read-method if it wants some other behavior.

However, my preferred solution would be to instead convert your object to a Data Transfer Object (DTO), add any required serialization attributes to this object, and use a library to serialize this. Added fields etc can usually be accommodated by just marking it as optional. Larger changes can usually be done by creating a new DTO class.

One way to solve your event problem could be to move this logic to a separate class

public class SuppressibleEvent
{
    private bool suppressEvents;
    private bool pendingEvent;
    public void Raise()
    {
        if (!suppressEvents)
        {
            TheChangeEvent?.Invoke(this, EventArgs.Empty);
        }
        else
        {
            pendingEvent = true;
        }
    }

    public event EventHandler TheChangeEvent;
    public bool SuppressEvents
    {
        get => suppressEvents;
        set
        {
            suppressEvents = value;
            if (!suppressEvents && pendingEvent)
            {
                TheChangeEvent?.Invoke(this, EventArgs.Empty);
                pendingEvent = false;
            }
        }
    }
}

Optionally you may add a interface, so that only the owner can raise the event, but others can listen and register. You could also add methods/events to your class that just forwards to the actual implementation.

The overall point is that there is usually a better pattern to use than implementation inheritance. Some might require a bit more code, but usually gain a bit of flexibility as a result.

Sign up to request clarification or add additional context in comments.

1 Comment

Thank you for this! I will definitely think about the Interface one. The example with the class for the event is along the lines of what I would do. The only problem there would be if I had a similarly constructed class for a completely unrelated bit of functionality that I would also like to add to a class, hence the question.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.