2

I have a proposed dictionary item schema that looks like this:

public interface IDataDictionary
{
    List<IDataDictionaryItem> DictionaryItems { get; set; }
}

And the dictionary items as:

public interface IDataDictionaryItem
{
    Guid Guild { get; set; }

    int SequenceId { get; set; }

    string Title { get; set; }

    string Value { get; set; }

    string Description { get; set; }

    string Language { get; set; }

} 

When I try to implement this in a concrete class like such:

public class HairColorDictionary : IDataDictionary
{
    public List<HairColor> DictionaryItems { get; set; }
}

With the items concrete implementation:

public class HairColor : IDataDictionaryItem
{
    public Guid Guild { get; set; }
    public int SequenceId { get; set; }
    public string Title { get; set; }
    public string Value { get; set; }
    public string Description { get; set; }
    public string Language { get; set; }
}

I get the error message below, and I can't seem to wrap my head around it. Can someone please enlighten me where this went wrong.

Error message:

Error CS0738 'HairColorDictionary' does not implement interface member 'IDataDictionary.DictionaryItems'. 'HairColorDictionary.DictionaryItems' cannot implement 'IDataDictionary.DictionaryItems' because it does not have the matching return type of 'List'.

Brian Rogers
  • 125,747
  • 31
  • 299
  • 300
Peter Koller
  • 312
  • 3
  • 16
  • 1
    There is a certain similarity to the referenced possible duplicate, but this certanly provided a better understanding of the problem/solution from a different point of view. – Peter Koller Dec 09 '18 at 05:39

2 Answers2

2

I understand what you're trying to get at and the reason it doesn't work is because the interface defined a collection that is non specific (that interface could be implemented), but you're trying to implement that interface member in a specific way.

If you really must do this you can do it with generics. Here's the updated bits:

public interface IDataDictionary<T> where T : IDataDictionaryItem
{
    List<T> DictionaryItems { get; set; }
}

public class HairColorDictionary : IDataDictionary<HairColor>
{
    public List<HairColor> DictionaryItems { get; set; }
}

T allows you to use anything and the where T:... part puts a constraint on it.

Please realize that is a potential answer to your solution. I've not taken the time to ponder the upsides or downsides of it.

The Muffin Man
  • 19,585
  • 30
  • 119
  • 191
  • 1
    That actually solved my problem, and also provided a better understanding of the workings of interface inheritance. Thank you! – Peter Koller Dec 09 '18 at 05:29
1

In your implementation, HairColorDictionary is-a IDataDictionary. So i could do something bad like:

IDataDictionary d = new HairColorDictionary();
d.DictionaryItems.add(blah);

Here add method expects something of type IDataDictionaryItem and not necessarily HairColor because d is just IDataDictionary and not HairColorDictionary! So i could do something like

class SkinColor : IDataDictionaryItem { ... }
IDataDictionaryItem s = new SkinColor();
d.DictionaryItems.add(s);

Question is whether this last statement is valid or not? It should be valid because add expects a IDataDictionaryItem which SkinColor correctly implements. But then it should not be valid because the actual public List<HairColor> DictionaryItems only allows HairColors and not SkinColors!!!

To eliminate all this confusion and to maintain strict type safety, you have to follow Covarience and Contravarience rules. Or you can go ahead with @TheMuffinMan's nice answer.

inquisitive
  • 3,549
  • 2
  • 21
  • 47
  • Yes, agreed. Before asking the question I was not realizing that possibility. Due to lack of understanding of course. I learned a valuable lesson with this. And thank you for also sheding some lite to it as well! – Peter Koller Dec 09 '18 at 05:47