Search code examples
c#dictionaryinterfacecovariance

IReadOnlyDictionary lack of covariance


I've read the related question (How to get around lack of covariance with IReadOnlyDictionary?), but I don't understand how it can help with my issue.

Here is the Box which can be edited (using IBoxTarget) and notify about changes (using IBoxSource):

interface IBoxTarget
{
    void DoSomething();
}

interface IBoxSource
{
    event Action SomethingIsDone;
}

class Box : IBoxTarget, IBoxSource
{
    public void DoSomething()
    {
        // . . . some logic . . .

        if (SomethingIsDone != null) SomethingIsDone();
    }

    public event Action SomethingIsDone;
}

Room is a container of Box. It also implements two interfaces:

interface IRoomTarget
{
    IReadOnlyDictionary<string, IBoxTarget> Boxes { get; }
}

interface IRoomSource
{
    IReadOnlyDictionary<string, IBoxSource> Boxes { get; }
}

class Room : IRoomTarget, IRoomSource
{
    Dictionary<string, Box> boxes = new Dictionary<string, Box>();

    IReadOnlyDictionary<string, IBoxTarget> IRoomTarget.Boxes
    {
        get { return boxes; } // Error: "Cannot implicitly convert type ..."
    }

    IReadOnlyDictionary<string, IBoxSource> IRoomSource.Boxes
    {
        get { return boxes; } // Error: "Cannot implicitly convert type ..."
    }
}

I don't want to create two different dictionaries inside Room. What do I need to do?


Solution

  • In my particular case this helped:

    interface IRoomTarget
    {
        IBoxTarget this[string name] { get; }
    }
    
    interface IRoomSource
    {
        IBoxSource this[string name] { get; }
    }
    
    class Room : IRoomTarget, IRoomSource
    {
        Dictionary<string, Box> boxes = new Dictionary<string, Box>();
    
        public IBoxTarget IRoomTarget.this[string name]
        {
            get { return boxes[name]; }
        }
    
        IBoxSource IRoomSource.this[string name]
        {
            get { return boxes[name]; }
        }
    }
    

    But I'm not sure that's universal solution