我有一个IReadOnlyDictionary<string, MyEnum>
集合需要传递给一个类,以便将其包含在MyEnum
中(注意MyEnum?
但不是IReadOnlyDictionary<string, MyEnum>
)。
我想出了两个设计:
将包装延迟到public class MyClass
{
private readonly IEnumerable<KeyValuePair<string, MyEnum?>> _kvps;
public MyClass(IEnumerable<KeyValuePair<string, MyEnum?>> kvps)
{
_kvps = kvps;
}
public IReadOnlyDictionary<string, MyEnum> Kvps
{
get
{
var filtered = from kvp in _kvps
where kvp.Value.HasValue
select kvp;
return new ReadOnlyDictionary<string, MyEnum>(
filtered.ToDictionary(kvp => kvp.Key, kvp => (MyEnum)kvp.Value);
}
}
}
,直到属性访问:
public class MyClass
{
public MyClass(IEnumerable<KeyValuePair<string, MyEnum?>> kvps)
{
Kvps = ToReadOnly(kvps);
}
public IReadOnlyDictionary<string, MyEnum> Kvps { get; }
private static IReadOnlyDictionary<string, MyEnum> ToReadOnly(
IEnumerable<KeyValuePair<string, MyEnum?>> kvps)
{
var filtered = from kvp in kvps
where kvp.Value.HasValue
select kvp;
return new ReadOnlyDictionary<string, MyEnum>(
filtered.ToDictionary(kvp => kvp.Key, kvp => (MyEnum)kvp.Value);
}
}
急切地评估构造函数中的集合
MyClass.Kvps
框架设计指南的constructor design部分表明,应该在构造函数中完成最少的工作,因此我选择了第一种方法。但是,这意味着每次调用_kvps
都会触发MyClass
的副本,这不是理想的。
我想知道哪种方法更好(或者有其他方法):
KeyValuePair
)[
{"name": "SpanningTree", "size": 3416},
{"name": "SpanningTree2", "size": 7312}
]
s的副本)答案 0 :(得分:1)
编辑:如果您想要最新的源值,最好的方法是实现自己的实现IReadOnlyDictionary
的类。使用ReadOnlyDictionary<string, MyEnum?>
的私有字段对其进行初始化。每个调用都将执行查找,如果键存在并且HasValue
,则返回值。
请注意,此实现取决于对作为IReadOnlyDictionary
传入的原始值的引用,以避免必须复制值。
public class MyReadOnlyDictionary<TKey, TValue> : IReadOnlyDictionary<TKey, TValue> where TValue : struct
{
// other methods to implement here...
public MyReadOnlyDictionary(IReadOnlyDictionary<TKey, TValue?> kvps)
{
_kvps = kvps;
}
private IReadOnlyDictionary<TKey, TValue?> _kvps;
new public TValue this[TKey key]
{
get
{
TValue? val = _kvps[key];
if (val.HasValue)
return val.Value;
throw new KeyNotFoundException();
}
}
}
答案 1 :(得分:1)
在这两个要求中 - 不要复制键值对并且不要存储两个副本 - 你必须打破一个。
是什么原因让我们看到这一点,并认为必须是一个解决方案,我们看到TValue
和TValue?
,我们的思想希望看到它们属于相同的类型。但它们不是同一类型。
如果您想象TValue
和TValue?
而不是int
和string
这两种不同类型,例如List<string> GetStringsFromNonNegativeInts(List<int> ints)
{
return ints.Where(i=>i>-1).Select(i=>i.ToString()).ToList();
}
和TValue?
,我们想要投射更清楚过滤时,一个集合到另一个集合中。例如,
TValue
与尝试将一组TValue
过滤到一组TValue?
的情况完全相同,即使没有字典也是如此。它更难看。 {{1}}和{{1}}代码使我们失明。
只有两种方法可以做到这一点。一种是每次复制,另一种是保持两个列表同步。