使用一个泛型类型创建自定义可迭代字典



我想创建一个包含唯一Type键的项目"列表",该键由项目本身的类型键控。我创建了一个收藏Dictionary<Type, V>并对其进行管理

internal class TypeCollection<V>
{
public TypeCollection()
{
items = new Dictionary<Type, V>();
}
private Dictionary<Type, V> items;
public void Add<T>(T value) where T : V
{
items.Add(typeof(T), value);
}
public void Remove(Type type)
{
items.Remove(type);
}
public bool TryGetValue<T>(out T value) where T : V
{
if (items.TryGetValue(typeof(T), out V foundValue))
{
value = (T)foundValue;
return true;
}
value = default(T);
return false;
}
}

我必须遍历这些值。for-loop是不可能的,因为我必须按其类型访问值,但foreach-loop可以完成这项工作。我实现了IEnumerable接口

TypeCollection<V> : IEnumerable<V>

并添加了所需的接口方法

public IEnumerator<V> GetEnumerator()
{
foreach (V value in items.Values)
{
yield return value;
}
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}

当我想从该集合中删除所有值时,我必须实现这个

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

正如你可能已经注意到的那样,我本来打算重新发明一本词典,为什么我要这么做。。。

我创建了这个

internal class TypeCollection<V> : Dictionary<Type, V>
{
public void Add<T>(T value) where T : V
{
Add(typeof(T), value);
}
public bool TryGetValue<T>(out T value) where T : V
{
if (TryGetValue(typeof(T), out V foundValue))
{
value = (T)foundValue;
return true;
}
value = default(T);
return false;
}
}

但是我不能覆盖默认的CCD_ 6和CCD_。我总是有两种方法,AddAdd<>,那么什么是"最干净"的方法?我想隐藏默认的AddTryGetValue方法,因为不再需要使用它们了。

您可以在System.Collections.Generic:中使用现有的KeyedByTypeCollection<TItem>,而不是创建自己的自定义TypeCollection<TValue>

KeyedByTypeCollection<TItem> Class

提供一个集合,该集合的项是用作键的类型。

备注

集合中只允许每种类型的一个对象,因为该类型是键,并且每个键必须是唯一的。但是你可以找到不同类型的物体。

然而,您可能需要将其子类化并扩展为包括一个方便的TryGetValue<T>(out T value),如

public class TypeCollection<V> : KeyedByTypeCollection<V>
{
public T ValueOrDefault<T>() where T : V
{
if (!Contains(typeof(T)))
{
return default(T);
}
return (T)this[typeof(T)];
}
public bool TryGetValue<T>(out T value) where T : V
{
if (!Contains(typeof(T)))
{
value = default(T);
return false;
}
value = (T)this[typeof(T)];
return true;
}
}

这是因为KeyedByTypeCollection<V>.Find<T>方法返回指定类型T集合中的第一个项,因此在具有复杂多态类型层次结构的情况下,当存在基类型时,它可能会返回派生类型的实例:

var dictionary = new KeyedByTypeCollection<object>();
dictionary.Add("hello");
dictionary.Add(new object());
Assert.IsTrue(dictionary.Find<object>().GetType() == typeof(object)); // FAILS

有关使用的更多示例,请参阅.Net?中KeyedByTypeCollection的使用。

您可以重新引入这些方法并使它们私有化:

private new void Add(Type key, V value)
{
}
private new bool TryGetValue(Type key, out V value)
{
value = default(V);
return false;
}

对于您的问题,有两种方法:继承和组合。继承不允许排除基类方法,因此Dictionary不是适合您的类型的最佳基类。

在合成中没有这样的问题,因为你决定了要公开什么方法。这是正常的方式。

解决方案:使用组合或找到新的更好的基类。

改为实现IDictionary接口:

internal class TypeCollection<V> : IDictionary<Type, V>
{
protected readonly Dictionary _innerDictionary = new Dictionary<Type,V>();
}

一旦您键入了那么多,VisualStudio就会在部分代码下加下划线,并显示一个错误,提醒您尚未实现该接口。右键单击错误并选择"通过_innerDictionary实现接口",它将自动生成将方法连接到_innerDictionary所需的一切。然后你可以修改任何你想要的。

最新更新