我想在 C# 中模仿 Python collections.defaultdict
。只要值类型具有无参数构造函数,以下就可以正常工作:
public class DefaultDictionary<TKey, TValue> : Dictionary<TKey, TValue> where TValue : new()
{
public new TValue this[TKey key]
{
get
{
TValue val;
if (!TryGetValue(key, out val)) {
val = new TValue();
Add(key, val);
}
return val;
}
set { base[key] = value; }
}
}
但是如果我想使用一个以键为参数的构造函数呢?或者一般来说,一个工厂函数,给定键,返回值类型的实例?
public class DefaultDictionary<TKey, TValue> : Dictionary<TKey, TValue> where TValue : new()
{
private readonly Func<TKey, TValue> factory;
public DefaultDictionary() : this(key => new TValue())
{}
public DefaultDictionary(Func<TKey, TValue> factory)
{
this.factory = factory;
}
public new TValue this[TKey key]
{
get
{
TValue val;
if (!TryGetValue(key, out val)) {
val = factory(key);
Add(key, val);
}
return val;
}
set { base[key] = value; }
}
}
现在的问题是 TValue
仍然需要有一个无参数的构造函数,即使使用了工厂函数。如果 Thingy
没有无参数构造函数,以下将不会编译:
new DefaultDictionary<int, Thingy>(key => new Thingy(key, otherStuff, moreStuff));
但是,删除约束会导致 new TValue()
语句中出现 CS0304 错误。
直觉上我想将类型约束放在 DefaultDictionary()
构造函数上,但我怀疑这是可能的。 C#有没有合适的方法可以解决这个问题?
答案 0 :(得分:1)
一种方法是仅保留采用 DefaultDictionary
中的值工厂的构造函数,并创建一个具有 : new()
约束的子类,并将无参数构造函数移到那里:
public class DefaultDictionaryParameterless<TKey, TValue> :
DefaultDictionary<TKey, TValue> where TValue : new()
{
public DefaultDictionaryParameterless()
: base(x => new TValue())
{
}
}
public class DefaultDictionary<TKey, TValue> : Dictionary<TKey, TValue>
{
private readonly Func<TKey, TValue> factory;
public DefaultDictionary(Func<TKey, TValue> factory)
{
this.factory = factory;
}
...
}