2013-02-16 5 views
9

Gibt es eine bessere Möglichkeit, Covariance in diesem Beispiel nachzuahmen? Im Idealfall würde ich gerne tun:KeyValuePair Covariance

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

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

Aber KeyValuePair<TKey, TValue> nicht covariant ist.

Stattdessen muß ich tun:

public IEnumerable<KeyValuePair<string, IEnumerable<string>>> Foos 
{ 
    get 
    { 
     return foos.Select(x => 
      new KeyValuePair<string, IEnumerable<string>>(x.Key, x.Value)); 
    } 
} 

Gibt es einen besseren/sauberen Weg?

Antwort

5

Leider ist KeyValuePair<TKey, TValue> eine Struktur; und Strukturen zeigen keine Varianz in .NET.

Sie können dies natürlich lösen, indem Sie Ihre eigene kovariante Pair Schnittstelle und einige einfache Helfer schreiben, um zwischen Sequenzen von KeyValuePair und Ihrer benutzerdefinierten Pair Schnittstelle zu konvertieren. So können Sie tun:

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

Hier einige Beispiel-Code, den Sie dies erreichen lässt:

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

Kaum. KVP ist eine Struktur: Keine iTernface, ist von ValueType.

Interessant SO post auf Varianz.

Ich denke, Abgüsse performanter sind, also würde ich so codieren bevorzugen:

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

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

Und werfen KeyValuePair.Value zu ICollection, wo ich wirklich brauchen. Ehrlich gesagt hängt es davon ab, wie foos verwendet wird.

Verwandte Themen