Maksim Simkin
Maksim Simkin

Reputation: 9679

Generic Interface with array of generics

Assume we have following interface:

public interface ILine<T>
{
    T Item { get; set;}
}

I do have classes Line1 and Line2 implementing it

public class Item1
{
}

public class Item2
{
}

public class Line1 : ILine<Item1>
{
    public Item1 Item {get; set;}   
}

public class Line2 : ILine<Item2>
{
    public Item2 Item { get; set; }
}

Now i have a class

public class Lines1
{
    public Line1[] Items { get; set;}
}

I would like to create an interface

public interface ILines<T>
{
    ILine<T>[] Items { get; set;}
}

And let Lines1 implement it Lines1 : ILines<Item1> (and Lines2 do the same with Item2). But it's not possible, because of complier error

'Lines1' does not implement interface member 'ILines.Items'. 'Lines1.Items' cannot implement 'ILines.Items' because it does not have the matching return type of 'IEnumerable>'.

The classes are deserialized from xml, so i really need properties as Item1, Item2, Line1, Line2 not as interfaces. What could i do to go forward? Or i am trying to apply some famous antipattern?

Update: Very good explanation, why it is not possible: covariance in c#

Unfortunately i haven't found it before writing question.

Upvotes: 1

Views: 887

Answers (2)

Hanuma
Hanuma

Reputation: 41

You may want to check this out.    

    public class LinesOne : ILines<Item1>
        {
            public ILine<Item1>[] Lines
            {
                get
                {
                    throw new NotImplementedException();
                }

                set
                {
                    throw new NotImplementedException();
                }
            }
        }

        public class LinesTwo : ILines<Item2>
        {
            public ILine<Item2>[] Lines
            {
                get
                {
                    throw new NotImplementedException();
                }

                set
                {
                    throw new NotImplementedException();
                }
            }
        }
        public interface ILines<T>
        {

            ILine<T>[] Lines { get; set; }
        }

        public interface ILine<T>
        {
            T Item { get; set; }
        }

        public class Item1
        {
        }

        public class Item2
        {
        }

        public class Line1 : ILine<Item1>
        {
            public Item1 Item { get; set; }
        }

        public class Line2 : ILine<Item2>
        {
            public Item2 Item { get; set; }
        }

Upvotes: 0

Luaan
Luaan

Reputation: 63722

ILine<T>[] is not the same as Line1[]. There's plenty of answers on SO about the concept of variance, they can explain this clearly.

The solution is to make sure the types actually map to each other. One way to do this is to make Line1 a generic argument as well:

interface ILines<T, U> where U : ILine<T>
{
  U[] Items { get; set; }
}

Sadly, this means you lose some of the type inferrence, so it can mean quite a bit of extra text.

Upvotes: 2

Related Questions