KeyValuePair协方差

时间:2013-02-16 11:52:59

标签: c# c#-4.0 covariance keyvaluepair

在这个例子中,有更好的方法来模仿协方差吗?理想情况下,我想这样做:

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));
    }
}

有更好/更清洁的方式吗?

2 个答案:

答案 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。