0

I am having an issue with classes that implement an interface that has a list of type some other interface. Tried to create a simple example below.

    public interface IPerson
{
    IEnumerable<IPersonEntry> Persons { get; set; }
    DateTime LastUpdated { get; set; }
}

public class PersonType1 : IPerson
{
    public IEnumerable<IPersonEntry> Persons { get; set; }
    public DateTime LastUpdated { get; set; }

    public PersonType1()
    {
        Persons = new List<NormalEntry>();
    }
}

public class PersonType2 : IPerson
{
    IEnumerable<IPersonEntry> Persons { get; set; }
    public DateTime LastUpdated { get; set; }

    public PersonType2()
    {
        Persons = new List<SomethingDifferent>();
    }
}

public interface IPersonEntry
{
    string Name { get; set; }
}

public class NormalEntry : IPersonEntry
{
    // some other props

}

public class SomethingDifferent  : IPersonEntry
{
    // something different
}

public class SomeOtherClass
{
    public SomeMethod()
    {
        PersonType2 p2 = new PersonType2();
        p2.Persons.Add(new SomethingDifferent{
            // blah = 5;
        })

    }
}

But in my SomeOtherClass method I want to be able to add to the List but its still getting treated like IEnumerable and not List<>. So I can't add to it. Any help would be greatly appreciated.

Matthew The Terrible
  • 1,589
  • 5
  • 31
  • 53

2 Answers2

8

You can't add to an IEnumerable<T>. Add method is defined in IList<T>, so you need to change your parameter type:

IList<IPersonEntry> Persons { get; set; }
Selman Genç
  • 100,147
  • 13
  • 119
  • 184
  • Alternatively, have the `Add` method in the `PersonType2` class, or cast to `List` in the `SomeOtherClass`. – Mephy Dec 06 '14 at 19:11
  • Oh nice. If I change to IList I get an error that I can't convert IList to List or whatever it would be. – Matthew The Terrible Dec 06 '14 at 19:13
  • 2
    @MatthewTheTerrible that's the classic covariance problem. see [this question](http://stackoverflow.com/questions/4034495/question-about-c-sharp-covariance) – Selman Genç Dec 06 '14 at 19:15
  • So is there a better approach to this problem then? – Matthew The Terrible Dec 06 '14 at 19:23
  • 1
    you are trying to violate type-safety. why do you want to add `SomethingDifferent` to a List of type `NormalEntry` ? if you explain what are you trying to achieve I can suggest a better solution. – Selman Genç Dec 06 '14 at 19:29
  • Oh sorry I think I screwed up my example. Was doing it from my memory. What I want to do is create the correct type of person I need depending on some value, probably use Factory here for this. Then I'll have a method that I will be calling that will be adding the correct type of entries to that newly created person type. But in the example above I'm adding something different to a list of type something different. Right? Person Type 2 has a list of type something different. – Matthew The Terrible Dec 06 '14 at 19:48
  • yes it is, sorry I missed it. but the problem is it's type known as `IList` so it migth be storing anything that implements IPersonEntry. that's why compiler doesn't allow you to add `SomethingDifferent`. What I can suggest in this situtation is to make `IPerson` generic and make the property generic as well. and implement it's generic version in your classes. for example in `PersonType1` implement `IPerson` . – Selman Genç Dec 06 '14 at 20:04
  • Oh wait in PersonTypes I can keep IList but in my method where I want to add things I can just add to the list new objects of whatever type I want right? This seems to work but seems dangerous that I could try to add anything to the list that implements that interface but it works. – Matthew The Terrible Dec 06 '14 at 20:22
2

Adding to Selman22's answer: The point is that the publicly visible definition of PersonType2.Persons is an IEnumerable, so it has to be treated like an IEnumerable - even if you chose List as an implementation for it. And as Selman said, you cannot add to an enumerable.

aufziehvogel
  • 7,167
  • 5
  • 34
  • 56