Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/list/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何制作此类自定义列表/集合_C#_List_Collections_Ienumerable - Fatal编程技术网

C# 如何制作此类自定义列表/集合

C# 如何制作此类自定义列表/集合,c#,list,collections,ienumerable,C#,List,Collections,Ienumerable,我正在尝试开发一个自定义集合或列表类,它为我提供以下功能: Add(MyObject) Add(MyObject, String) ' key Remove(MyObject) RemoveByKey(String) ' key RemoveAt(Index) Count Clear Item(Index) Item(String) ' key Contains(MyObject) ContainsKey(String) ' key GetEnumerator ' for-each

我正在尝试开发一个自定义集合或列表类,它为我提供以下功能:

Add(MyObject)
Add(MyObject, String)   ' key
Remove(MyObject)
RemoveByKey(String) ' key
RemoveAt(Index)
Count
Clear
Item(Index)
Item(String)    ' key
Contains(MyObject)
ContainsKey(String) ' key
GetEnumerator   ' for-each MyObject
我已经搜索了IEnumerable、IList和ICollection,但没有一个能满足我上面的需求。例如,它们都缺少按键(字符串)存储对象。 如何创建这样的集合/列表对象?我注意到,与我的需求最匹配的是系统可用的ListViewItemCollection对象。我希望我能看到其中的编码,以了解它是如何实现对象的存储和检索的

有人能帮忙吗?或者引导我找到教程链接


谢谢。

此类类的示例可以是System.Windows.Forms.Control.ControlCollection,它的实现方式类似于
列表(实际上控件已经包含键),
此[字符串]
使用普通for循环(线性搜索键)实现

我们可以通过添加Dictionary来帮助加快这一速度,并向两个集合(列表+Dictionary)添加每个具有键的项。不带键的项目仅添加到列表中

编辑:进一步的改进可以使用
列表
字典
-将索引从列表映射到字典,以便更快地删除。RemoveAt应检查键是否已预设,并将其从字典中删除。RemoveByKey可以获取内部List.RemoveAt的索引

基于注释的插件:IEnumerable的实现可能如下所示:

class MyObjectList<T>: IEnumerable<T> {
public IEnumerator<T> GetEnumerator() {
    T[] a = items; int n = size;
    for(int i = 0; i < n; i++)
        yield return a[i]; }
IEnumerator IEnumerable.GetEnumerator() {
    return GetEnumerator(); }
类MyObjectList:IEnumerable{
公共IEnumerator GetEnumerator(){
T[]a=项目;int n=大小;
对于(int i=0;i
…以上是
列表


插件:和(可以随意使用)。

我打赌有很多更简单的方法可以做到这一点,但这里有一种方法。您可以创建一个
结构,其中包含每个项目的键和值:

public sealed class Listionary<K, T> : IDictionary<K, T>, IList<T>
{
    private struct ListionaryPair
    {
        public ListionaryPair(T item) : this()
        {
            Item = item;
        }

        public ListionaryPair(K key, T item) : this()
        {
            Key = key;
            Item = item;
        }

        public K Key { get; private set; }
        public T Item { get; private set; }
        public bool HasKey { get; private set; }
    }

    private readonly List<ListionaryPair> list = new List<ListionaryPair>();
可以通过显式实现隐藏丑陋的方法:

    void ICollection<KeyValuePair<K, T>>.CopyTo(KeyValuePair<K, T>[] array, int arrayIndex)
    {
        // code implementing the method
    }
void ICollection.CopyTo(KeyValuePair[]数组,int-arrayIndex)
{
//实现该方法的代码
}
您需要一些助手方法来按键访问:

    private int IndexOfKey(K key)
    {
        for (int i = 0; i < list.Count; i++)
        {
            var pair = list[i];
            if (pair.HasKey && pair.Key == key)
            {
                return i;
            }
        }

        return -1;
    }
private int IndexOfKey(K键)
{
for(int i=0;i
但如果你做对了,剩下的就没有那么大的挑战了:

    public T this[K key]
    {
        get
        {
            int index = IndexOfKey(key);
            if (index < 0)
            {
                throw new IndexOutOfRangeException();
            }

            return list[index].Item;
        }
        set
        {
            int index = IndexOfKey(key);
            if (index < 0)
            {
                throw new IndexOutOfRangeException();
            }

            list[index] = new ListionaryPair(key, value);
        }
    }
public T此[K键]
{
得到
{
int index=IndexOfKey(键);
如果(指数<0)
{
抛出新的IndexOutOfRangeException();
}
返回列表[索引]。项;
}
设置
{
int index=IndexOfKey(键);
如果(指数<0)
{
抛出新的IndexOutOfRangeException();
}
列表[索引]=新的ListionaryPair(键,值);
}
}
完成每个接口方法需要相当多的编码,但大多数都是简短的。您必须决定是否允许使用同一个键的多个项,是
IDictionary.Clear()
清除整个集合还是只清除键控项,等等


此外,本例中没有支持
字典
,因此性能可能不太好。

听起来您需要一本字典。要添加到@SLaks注释中,Microsoft在此处为其
字典
的实现提供了源代码:但这看起来更像是一本
有序字典
,因为他想访问s项目也按索引。我将组合两个容器-带键的容器为字典,所有容器为列表。索引与键相关吗?@SLaks我不建议使用
OrderedDictionary
,我将
Dictionary
与他正在寻找的内容进行了比较。我不是要攻击你的评论,只是试图帮助提高速度不是问题。col我想我尝试开发的选择不会保留超过50个项目。但是在字典和列表中保留一个对象不是对内存的负担吗?如果速度不是问题,那么我会和ControlCollection一样。但是我喜欢优化速度,内存开销不会太大(比如*2或*3——这不是问题,速度可能会有问题)我使用一个内部列表和字典来管理Add、Remove、RemoveAt、RemoveByKey等。但是对于GetEnumerator,我认为我需要实现一些接口。它应该是IList还是IcolAction或者其他什么?GetEnumerator是足够的,但是你应该添加
IEnumerable
接口。GetEnumerator()很简单:
foreach(innerList中的KeyValuePair对)yield return pair.Value;
我检查了您的@firda ListCore示例以及我在网上找到的一些其他自定义集合源代码,我注意到许多自定义集合使用数组来处理它们的工作,而不是依赖于IList或ICollection之类的内置接口。这些接口上的性能真的很差吗必须求助于手动管理的数组?
公共接口IDictionary:ICollection、IEnumerable、IEnumerable
…因此,我宁愿坚持使用KeyValuePair,并使用null表示无键…但是+1表示努力(回答很好,很长)。
    public T this[K key]
    {
        get
        {
            int index = IndexOfKey(key);
            if (index < 0)
            {
                throw new IndexOutOfRangeException();
            }

            return list[index].Item;
        }
        set
        {
            int index = IndexOfKey(key);
            if (index < 0)
            {
                throw new IndexOutOfRangeException();
            }

            list[index] = new ListionaryPair(key, value);
        }
    }