Как создать класс коллекции, содержащий список абстрактных элементов - PullRequest
0 голосов
/ 21 марта 2012

Мне нужно создать коллекцию, содержащую список абстрактных сегментов.

У меня есть ряд производных классов из сегмента, т. Е. LineSegment : Segment

public class Path : IEnumerable
{
        private List<Segment> segments = new List<Segment>();


        public List<Segment> Segments 
        {  
            set { Segments = value;}
            get { return this.segments; } 
        }
        //some code inc ctrs

}

Я бы хотелбыть в состоянии определить LinePath как производный класс от базового класса Path

public class LinePath : Path, IEnumerable
{        
        public LinePath(List<LineSegment> s)
        {
            this.Segments = s; //error
        }
}

Однако я продолжаю сталкиваться с ситуациями, когда я не могу легко редактировать содержимое LinePath из-за спискаон по-прежнему содержит список Segment (много приведения) или когда я хочу создать нормальный Path из LinePath плюс другие производные сегменты.

Каким будет стандартный формат для этого видапроблемы?Может быть, я должен отказаться от LinePath и просто работать с Path объектами?

Я понимаю, что в этом вопросе может быть небольшая неопределенность, я прошу прощения за это, но мне нужно разобраться, что на самом делевызывает у меня путаницу и позволяет избежать грязного решения.

Ответы [ 3 ]

0 голосов
/ 21 марта 2012

вижу пару вариантов. Во-первых, ищите возможности использовать ваш список как IEnumerable<T>, а не List<T>, потому что List<LineSegment> можно использовать как IEnumerable<Segment> просто путем приведения списка, без приведения всех элементов ( предполагая, что C # 4.0 или позже).

Во-вторых, рассмотрите возможность сделать Path производным от сегмента (PathSegment, если хотите), так что вы можете включить LinePath в Path как отдельный объект, а не добавлять все его элементы LineSegment в список Path элементов Segment. .

Возможно, вы захотите опубликовать большую выдержку из своего кода на codereview.stackexchange.com.

0 голосов
/ 21 марта 2012

Я думаю, что лучше определить, что универсальный параметр T должен иметь тип сегмента. Чтобы избежать чего-то вроде Path<string>.

Также вам не нужно наследовать LinePath от IEnumerable - он унаследует эту реализацию интерфейса от Path. И рассмотрите возможность использования универсальной версии интерфейса IEnumerable.

  public class Path<T> : IEnumerable<T>
        where T : Segment // here we define that parameter is Segment or its child
    {
        private List<T> _segments = new List<T>();        

        public List<T> Segments
        {
            set { _segments = value; }
            get { return _segments; }
        }

        public IEnumerator GetEnumerator()
        {
            throw new NotImplementedException();
        }
    }

    public class LinePath<T> : Path<T> 
        where T : LineSegment // parameter is LineSegment or its child
    {

        public LinePath(List<T> segments)
        {
            // no error because Path.Segments of type List<LineSegment>
            Segments = segments;
        }
    }
0 голосов
/ 21 марта 2012

Я не знаю, правильно ли я понимаю вопрос, но я думаю, что именно такое поведение вы хотите.

public class GenericPath<T> : IEnumerable
    {
        private List<T> items = new List<T>();


        public List<T> Items
        {
            set { this.items = value; }
            get { return this.items; }
        }
        //some code inc ctrs

    }

    public class Segment
    {
    }

    public class Path : GenericPath<Segment>
    {        

    }

    public class LinePath : GenericPath<Path>
    {
    }
...