我想创建一个包含唯一的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;
}
}
但是我无法覆盖默认的Add
和TryGetValue
方法。我将同时拥有Add
和Add<>
这两种方法,那么“最干净”的方法是什么?我想隐藏默认的Add
和TryGetValue
方法,因为不再需要使用它们。
答案 0 :(得分:4)
您可以使用TypeCollection<TValue>
中现有的KeyedByTypeCollection<TItem>
,而不是创建自己的自定义System.Collections.Generic
:
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
有关更多使用示例,请参见 Uses of KeyedByTypeCollection in .Net? 。
答案 1 :(得分:1)
您可以重新引入这些方法并将其设为私有:
private new void Add(Type key, V value)
{
}
private new bool TryGetValue(Type key, out V value)
{
value = default(V);
return false;
}
答案 2 :(得分:1)
对于您的问题,有两种方法:继承和组合。
继承不允许您排除基类方法,因此Dictionary
不是您类型的最佳基类。
在合成中没有这样的问题,因为您不愿公开什么方法。这是正常的方式。
解决方案:使用组合物或找到新的更好的基类。
答案 3 :(得分:0)
改为使用IDictionary
界面:
internal class TypeCollection<V> : IDictionary<Type, V>
{
protected readonly Dictionary _innerDictionary = new Dictionary<Type,V>();
}
一旦键入那么多,Visual Studio就会在代码的下划线处显示错误,并提醒您尚未实现该接口。右键单击错误,然后选择“通过_innerDictionary实现接口”,它将自动生成将方法连接到_innerDictionary
所需的所有内容。然后,您可以修改任何内容。