2013-02-16 58 views
9

क्या इस उदाहरण में कोविरिएंस की नकल करने का कोई बेहतर तरीका है? आदर्श रूप में मैं क्या करना चाहते हैं:KeyValuePair Covariance

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

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

लेकिन KeyValuePair<TKey, TValue> covariant नहीं है।

इसके बजाय मैं क्या करना है:

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> एक संरचना है; और structs .NET में भिन्नता प्रदर्शित नहीं करते हैं।

आप निश्चित रूप से अपने खुद के covariant Pair इंटरफेस और कुछ सरल सहायकों लेखन KeyValuePair के दृश्यों और अपने कस्टम Pair इंटरफ़ेस के बीच परिवर्तित करने के लिए द्वारा इस का समाधान कर सकते हैं। यह आपको करने देंगे:

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

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

यहाँ आप इस लक्ष्य को हासिल करने देगा कि कुछ उदाहरण कोड है

0

शायद ही कभी। केवीपी एक संरचना है: इटनेरफेस नहीं, वैल्यू टाइप का है।

भिन्नता पर SO post दिलचस्प।

मुझे लगता है कि डाले अधिक performant हैं, इसलिए मैं इस तरह कोड करने के लिए पसंद करते हैं:

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

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

और ICollection को KeyValuePair.Value डाली जहां मैं सच में की जरूरत है। स्पष्ट रूप से यह इस बात पर निर्भर करता है कि फ़ूज़ का उपयोग कैसे किया जाता है।