【问题标题】:C# How to create a Generic List Collection with a IEnumeratorC# 如何使用 IEnumerator 创建通用列表集合
【发布时间】:2011-06-22 06:50:25
【问题描述】:

您好,我在这里遇到语法问题,完全不知道如何正确执行此操作。

我的自定义列表来源:(有错误)GetEnmerator() 和大量警告

错误和警告是:

错误 1“EntityListEnumerator”未实现接口成员“System.Collections.IEnumerator.Current”。 “EntityListEnumerator.Current”无法实现“System.Collections.IEnumerator.Current”,因为它没有“object”的匹配返回类型。
警告 2 'EntityList.Add(T)' 隐藏继承的成员 'System.Collections.Generic.List.Add(T)'。如果要隐藏,请使用 new 关键字。
警告 3 'EntityList.this[int]' 隐藏了继承的成员 'System.Collections.Generic.List.this[int]'。如果要隐藏,请使用 new 关键字。
警告 4 'EntityList.Remove(T)' 隐藏继承的成员 'System.Collections.Generic.List.Remove(T)'。如果要隐藏,请使用 new 关键字。
警告 5 'EntityList.IndexOf(T)' 隐藏继承的成员 'System.Collections.Generic.List.IndexOf(T)'。如果要隐藏,请使用 new 关键字。
警告 6 'EntityList.Contains(T)' 隐藏继承的成员 'System.Collections.Generic.List.Contains(T)'。如果要隐藏,请使用 new 关键字。
警告 7 'EntityList.Count' 隐藏了继承的成员 'System.Collections.Generic.List.Count'。如果要隐藏,请使用 new 关键字。

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 源,到处都有错误,主要是一些与我的真实 Type 到 Generic 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;
    }
}

如何修复该错误并正确消除这些警告。谢谢

【问题讨论】:

    标签: visual-studio list generics collections ienumerable


    【解决方案1】:

    您需要为 IEnumerator 实现属性object Current

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

    此外,由于您的列表类继承了 List,因此您不能覆盖 List 的方法,因为它们不是虚拟的。您可以实现自己的实现 ICollection 的类。我为此创建了一个代码 sn-p 供您使用:

    <?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。

    【讨论】:

    • 哇,不错,是的,我想我必须使用 ICollection 而不是 IList,但我无法实现所有剩余的接口成员,那代码 sn-p 是什么格式.. 似乎没有像 C# 文件格式,但我看到下面的代码有点我假设美元符号 = ,我想我只是用 EntityList 替换 $name$ 和用 Entity 替换 $type$?
    • @SSpoke 您可以将该 sn-p 导入 VS2010:工具/代码片段管理器/导入...要使用它,您只需开始输入“集合”,智能感知建议您插入此代码 sn-页。我插入了一个可以复制的骨架类:pastebin.com/EMyYFC4A
    • 感谢您的帮助,这是一个非常好的和简单的收集实现,甚至在谷歌上都找不到这样的东西。
    【解决方案2】:

    只需从 Collection 派生并覆盖您要更改其行为的方法。完全没有必要重新实现你所做的所有成员。

    此外,您应该看看yield 关键字,它可以让您轻松创建自己的 IEnumerator 类型。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2010-12-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-03-10
      相关资源
      最近更新 更多