2013-02-16 79 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。