在这个例子中,有更好的方法来模仿协方差吗?理想情况下,我想这样做:
private IDictionary<string, ICollection<string>> foos;
public IEnumerable<KeyValuePair<string, IEnumerable<string>> Foos
{
get
{
return foos;
}
}
但是KeyValuePair<TKey, TValue>
不是协变的。
相反,我必须这样做:
public IEnumerable<KeyValuePair<string, IEnumerable<string>>> Foos
{
get
{
return foos.Select(x =>
new KeyValuePair<string, IEnumerable<string>>(x.Key, x.Value));
}
}
有更好/更清洁的方式吗?
答案 0 :(得分:6)
不幸的是,KeyValuePair<TKey, TValue>
是一个结构;和结构在.NET中不会出现差异。
您当然可以通过编写自己的协变Pair
接口和一些简单的帮助程序来解决此问题,以便在KeyValuePair
和自定义Pair
接口的序列之间进行转换。这将让你做到:
var dict = new Dictionary<string, ICollection<string>>();
// Notice that you can "weaken" both the key and the value.
var dictView = dict.GetCovariantView()
.CastPairs<object, IEnumerable<string>>();
以下是一些示例代码,可以让您实现此目的:
public interface IPair<out TKey, out TValue>
{
TKey Key { get; }
TValue Value { get; }
}
public class Pair<TKey, TValue> : IPair<TKey, TValue>
{
public TKey Key { get; private set; }
public TValue Value { get; private set; }
public Pair(TKey key, TValue value)
{
Key = key;
Value = value;
}
public Pair(KeyValuePair<TKey, TValue> pair)
: this(pair.Key, pair.Value) { }
}
public static class PairSequenceExtensions
{
public static IEnumerable<IPair<TKey, TValue>> GetCovariantView<TKey, TValue>
(this IEnumerable<KeyValuePair<TKey, TValue>> source)
{
if (source == null)
throw new ArgumentNullException("source");
return source.Select(pair => new Pair<TKey, TValue>(pair));
}
public static IEnumerable<IPair<TKey, TValue>> CastPairs<TKey, TValue>
(this IEnumerable<IPair<TKey, TValue>> source)
{
if (source == null)
throw new ArgumentNullException("source");
return source;
}
}
答案 1 :(得分:0)
几乎没有。 KVP是一个结构:不是一个itnerface,是ValueType。
对方差感兴趣SO post。
我认为演员阵容性能更高,所以我更喜欢像这样编码:
private IDictionary<string, IEnumerable<string>> foos;
public IEnumerable<KeyValuePair<string, IEnumerable<string>> Foos
{
get
{
return foos;
}
}
将KeyValuePair.Value
投射到我真正需要的地方ICollection
。坦率地说,这取决于如何使用foos。