我正在尝试开发一个自定义集合或列表类,它为我提供了以下功能:
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对象。我希望我能在其中看到编码,以了解它是如何实现对象的存储和检索的。
有人可以帮忙吗?或者引导我学习教程链接。
感谢。
答案 0 :(得分:1)
这样的类的示例可以是System.Windows.Forms.Control.ControlCollection,它实现为List<KeyValuePair<string,Control>>
(实际上Control已包含密钥),this[string]
使用普通的for-loop实现(线性)寻找钥匙)。
我们可以通过添加Dictionary并将带有键的每个项目添加到两个集合(List + Dictionary)来帮助加快速度。没有键的项目仅添加到列表中。
编辑:进一步改进可能会使用List<KeyValuePair<string,T>>
和Dictionary<string,KeyValuePair<int,T>>
- 将列表中的索引映射到字典,以便更快地删除。 RemoveAt应检查密钥是否已预设,并将其从字典中删除。 RemoveByKey可以获取内部List.RemoveAt的索引。
基于评论的ADDON: IEnumerable<T>
的实施可能如下所示:
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(); }
......以上是List<T>
ADDON: here you can see my custom ListCore和List created from it(随意使用它)。
答案 1 :(得分:1)
我敢打赌有很多简单的方法可以做到这一点,但这是一种方法。您可以创建一个struct
,其中包含每个项目的键和值:
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>();
(整个HasKey
事物允许值类型为K
或null
引用作为有效键。如果您只想要string
个键,则可以用{替换此结构{1}})
然后两个接口分开:
KeyValuePair<string, T>
您可以通过显式实现它们来隐藏丑陋的方法:
public void Add(T item)
{
list.Add(new ListionaryPair(item));
}
public void Add(K key, T item)
{
list.Add(new ListionaryPair(key, item));
}
public void RemoveAt(int index)
{
list.RemoveAt(index);
}
您需要一些辅助方法来按键访问:
void ICollection<KeyValuePair<K, T>>.CopyTo(KeyValuePair<K, T>[] array, int arrayIndex)
{
// code implementing the method
}
但是如果你把它们弄好了,剩下的就不会那么大了:
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;
}
完成每种接口方法需要相当多的编码,但大多数都是简短的。您必须决定是否允许使用相同键的多个项目, 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);
}
}
是清除整个集合还是仅清除键控项目等。
此示例中也没有后备IDictionary<,>.Clear()
,因此性能可能不会那么好。