C # Как создать универсальную коллекцию списков с помощью IEnumerator - PullRequest
2 голосов
/ 22 июня 2011

Здравствуйте, у меня возникли проблемы с синтаксисом, и я совершенно не понимаю, как это сделать правильно.

Источник моего пользовательского списка: (с ошибками) в GetEnmerator () и множестве предупреждений

Ошибка и предупреждения:

Ошибка 1 «EntityListEnumerator» не реализует элемент интерфейса «System.Collections.IEnumerator.Current». «EntityListEnumerator.Current» не может реализовать «System.Collections.IEnumerator.Current», поскольку у него нет соответствующего возвращаемого типа «object».
Предупреждение 2 «EntityList.Add (T)» скрывает унаследованный член «System.Collections.Generic.List.Add (T)». Используйте новое ключевое слово, если было скрыто.
Предупреждение 3 «EntityList.this [int]» скрывает унаследованный член «System.Collections.Generic.List.this [int]». Используйте новое ключевое слово, если было скрыто.
Предупреждение 4 «EntityList.Remove (T)» скрывает унаследованный член «System.Collections.Generic.List.Remove (T)». Используйте новое ключевое слово, если целью было скрытие.
Предупреждение 5 «EntityList.IndexOf (T)» скрывает унаследованный член «System.Collections.Generic.List.IndexOf (T)». Используйте новое ключевое слово, если нужно было скрыть.
Предупреждение 6 «EntityList.Contains (T)» скрывает унаследованный член «System.Collections.Generic.List.Contains (T)». Используйте новое ключевое слово, если было скрыто.
Предупреждение 7 «EntityList.Count» скрывает унаследованный член «System.Collections.Generic.List.Count». Используйте новое ключевое слово, если было скрыто.

class EntityList<T> : List<T>, IEnumerable<T> where T : Entity
{
    private const int DEFAULT_CAPACITY = 1600, MIN_VALUE = 1;
    public T[] entities;
    public HashSet<int> indicies = new HashSet<int>();
    public int curIndex = MIN_VALUE;
    public int capacity;

    public EntityList(int capacity) {
        entities = new T[capacity];
        this.capacity = capacity;
    }

    public EntityList() 
        : this(DEFAULT_CAPACITY) {}

    public bool Add(T entity)
    {
        Add(entity, curIndex);
        return true;
    }

    public void Add(T entity, int index) {
        if (entities[curIndex] != null) {
            increaseIndex();
            Add(entity, curIndex);
        } else {
            entities[curIndex] = entity;
            entity.setIndex(index);
            indicies.Add(curIndex);
            increaseIndex();
        }
    }

    public T this[int index]
    {
        get
        {
            return entities[index];
        }
        set
        {
            entities[index] = value;
        }
    }

    public void Remove(T entity)
    {
        entities[entity.getIndex()] = null;
        indicies.Remove(entity.getIndex());
        decreaseIndex();
    }

    public Entity Remove(int index)
    {
        Object temp = entities[index];
        entities[index] = null;
        indicies.Remove(index);
        decreaseIndex();
        return (Entity)temp;
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return new EntityListEnumerator<T>(entities, indicies, this);
    }

    private void increaseIndex() {
        curIndex++;
        if (curIndex >= capacity) {
            curIndex = MIN_VALUE;
        }
    }

    private void decreaseIndex()
    {
        curIndex--;
        if (curIndex <= capacity)
            curIndex = MIN_VALUE;
    }

    public int IndexOf(T entity) {
        foreach(int index in indicies) {
            if (entities[index].Equals(entity)) {
                return index;
            }
        }
        return -1;
    }

    public bool Contains(T entity)
    {
        return IndexOf(entity) > -1;
    }

    public int Count {
        get
        {
            return indicies.Count();
        }
    }
}

Вот мой источник EntityListEnumerator с ошибками повсюду, в основном, с некоторыми разговорами о боксе с моим настоящим типом типа T на тип

class EntityListEnumerator<T> : IEnumerator<T> where T : Entity
{
    private int[] indicies;
    private object[] entities;
    private EntityList<T> entityList;

    protected int curIndex; //current index
    protected T _current; //current enumerated object in the collection

    public EntityListEnumerator(object[] entities, HashSet<int> indicies, EntityList<T> entityList)
    {
        this.entities = entities;
        this.indicies = indicies.ToArray();
        this.entityList = entityList;
        curIndex = -1;
    }

    public virtual T Current
    {
        get
        {
            return _current;
        }
    }

    public virtual bool MoveNext()
    {
        //make sure we are within the bounds of the collection
        if (++curIndex >= entityList.Count)
        {
            //if not return false
            return false;
        }
        else
        {
            //if we are, then set the current element
            //to the next object in the collection
            _current = entityList[indicies[curIndex]];
        }
        //return true
        return true;
    }

    public void Remove() {
        if (curIndex >= 1)
        {
            entityList.Remove(indicies[curIndex - 1]);
        }
    }

    // Reset the enumerator
    public virtual void Reset()
    {
        _current = default(T); //reset current object
        curIndex = -1;
    }

    // Dispose method
    public virtual void Dispose()
    {
        entityList = null;
        _current = default(T);
        curIndex = -1;
    }
}

Как исправить эту ошибку и правильно избавиться от этих предупреждений. Спасибо

Ответы [ 2 ]

2 голосов
/ 22 июня 2011

Вам необходимо реализовать свойство object Current для IEnumerator:

class EntityListEnumerator<T> : IEnumerator<T> where T : Entity
{
    //....
    object IEnumerator.Current
    {
        get { return Current; }
    }
    //....
}

Кроме того, поскольку ваш класс списка наследует List <>, вы не можете переопределить методы List <>, поскольку они не являются виртуальными. Вы можете реализовать свой собственный класс, который реализует ICollection <>. Для этого я создал фрагмент кода, который вы можете использовать:

<?xml version="1.0" encoding="utf-8"?>
<CodeSnippets xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet">
    <CodeSnippet Format="1.0.0">
        <Header>
            <Title>ICollection class</Title>
            <Author>Torbjörn Hansson</Author>
            <Description>Implement a generic ICollection class.</Description>
            <SnippetTypes>
                <SnippetType>Expansion</SnippetType>
            </SnippetTypes>
            <Shortcut>collection</Shortcut>
        </Header>
        <Snippet>
            <Declarations>
                <Literal>
                    <ID>name</ID>
                    <ToolTip>The name of the class</ToolTip>
                    <Default>MyCollection</Default>
                </Literal>
                <Literal>
                    <ID>type</ID>
                    <ToolTip>The type for the ICollection</ToolTip>
                    <Default>string</Default>
                </Literal>
            </Declarations>
            <Code Language="CSharp">
                <![CDATA[
    public class $name$ : ICollection<$type$>
    {
        public $name$()
        {
            this.items = new List<$type$>();
        }

        public $name$(IEnumerable<$type$> collection)
        {
            this.items = new List<$type$>(collection);
        }

        // inner collection
        private List<$type$> items;

        public void Add($type$ item)
        {
            this.items.Add(item);
        }

        public void Clear()
        {
            this.items.Clear();
        }

        public bool Contains($type$ item)
        {
            return this.items.Contains(item);
        }

        public void CopyTo($type$[] array, int arrayIndex)
        {
            this.items.CopyTo(array, arrayIndex);
        }

        public int Count
        {
            get { return this.items.Count; }
        }

        public bool IsReadOnly
        {
            get { return false; }
        }

        public bool Remove($type$ item)
        {
            return this.items.Remove(item);
        }

        public IEnumerator<$type$> GetEnumerator()
        {
            return this.items.GetEnumerator();
        }

        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            return this.items.GetEnumerator();
        }
    }
        ]]>

            </Code>
        </Snippet>
    </CodeSnippet>
</CodeSnippets>

Или просто измените свой класс EntityList <> для реализации IList <> вместо List <>.

1 голос
/ 22 июня 2011

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

Кроме того, вам следует взглянуть на ключевое слово yield, которое позволяет легко создавать собственные типы IEnumerator.

...