2013-02-16 76 views
9

在这个例子中是否有更好的方法来模拟协方差?理想情况下我想这样做: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)); 
    } 
} 

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

回答

5

不幸的是,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; 
    } 
} 
0

几乎没有。 KVP是一个结构:不是itnerface,是ValueType。

有趣的SO post的差异。

我认为铸件是更好的性能,所以我更喜欢这样的代码:

private IDictionary<string, IEnumerable<string>> foos; 

public IEnumerable<KeyValuePair<string, IEnumerable<string>> Foos 
{ 
    get 
    { 
     return foos; 
    } 
} 

而且投KeyValuePair.ValueICollection,我真的需要。坦率地说,这取决于如何使用foos。