Home > other >  Working around the lack of enum inheritance
Working around the lack of enum inheritance

Time:10-21

Classes Phone and Computer both implement the IDevice interface.

Phone has a PhoneStatus enum property, while Computer has a ComputerStatus enum property. Moreover, they both have a method that returns some stuff based on their status property.

class Phone : IDevice
{
    public string Name { get; set; }
    public string Manufacturer { get; set; }
    public PhoneStatus Status { get; set; }
    
    IEnumerable<object> GetStuffByStatus(PhoneStatus status)
    {
        ...
    }
}

enum PhoneStatus
{
    On,
    Off
}

class Computer : IDevice
{
    public string Name { get; set; }
    public string Manufacturer { get; set; }
    public ComputerStatus Status { get; set; }
    
    IEnumerable<object> GetStuffByStatus(ComputerStatus status)
    {
        ...
    }
}

enum ComputerStatus
{
    Started,
    ShutDown,
    Booting,
    ShuttingDown
}

I know inheritance is not an option for enums, so the question is: is there any way to force the classes implementing IDevice to write their own DeviceStatus property (which could be implemented as a PhoneStatus or a ComputerStatus) and GetStuffByStatus method? Something like this

interface IDevice
{
    string Name { get; set; }
    string Manufacturer { get; set;}
    DeviceStatus Status { get; set;}
    
    IEnumerable<object> GetStuffByStatus(DeviceStatus status);
}

CodePudding user response:

You could try something like this:

public interface IDevice<T> where T: Enum
{
    string Name         { get; set; }
    string Manufacturer { get; set; }
    T Status { get; set; }

    IEnumerable<object> GetStuffByStatus(T status);
}

Then implementing classes must declare an enum of some kind for the status:

public class Computer: IDevice<ComputerStatus>
{
    public string Name { get; set; }
    public string Manufacturer { get; set; }
    public ComputerStatus Status { get; set; }

    public IEnumerable<object> GetStuffByStatus(ComputerStatus status)
    {
        throw new NotImplementedException();
    }
}

If you need to, you could extract the common parts that are not dependent on the Status enum into a base interface:

public interface IDevice
{
    string Name         { get; set; }
    string Manufacturer { get; set; }
}

public interface IDeviceWithStatus<T>: IDevice where T: Enum
{
    T Status { get; set; }
    IEnumerable<object> GetStuffByStatus(T status);
}

Then you'll still be able to access the common parts via IDevice and the status-dependent parts via IDeviceWithStatus<T>.

CodePudding user response:

Inheritance is something that nowadays is considered as little outdated and clumsy way of solving problems. So IMO it would be actually better to just create two enums with very same values instead of using inheritance and tightly coupling two unconnected types (from business perspective). But if you are ok with inheritance anyway you can consider using your own implementation of enums like showed here for example https://learn.microsoft.com/en-us/dotnet/architecture/microservices/microservice-ddd-cqrs-patterns/enumeration-classes-over-enum-types In this way you would be able to use inheritance as you wished

  • Related