c# - Covarianza de KeyValuePair
c#-4.0 covariance (2)
Apenas. KVP es una estructura: no es una interfaz, es de ValueType.
Interesante publicación SO sobre la varianza.
Creo que los moldes son más efectivos, así que prefiero codificar de esta manera:
private IDictionary<string, IEnumerable<string>> foos;
public IEnumerable<KeyValuePair<string, IEnumerable<string>> Foos
{
get
{
return foos;
}
}
Y lanzar KeyValuePair.Value
a ICollection
donde realmente lo necesito. Hablando francamente, depende de cómo se usa foos.
¿Hay una mejor manera de imitar la covarianza en este ejemplo? Idealmente me gustaría hacer:
private IDictionary<string, ICollection<string>> foos;
public IEnumerable<KeyValuePair<string, IEnumerable<string>> Foos
{
get
{
return foos;
}
}
Pero KeyValuePair<TKey, TValue>
no es covariante.
En cambio, tengo que hacer:
public IEnumerable<KeyValuePair<string, IEnumerable<string>>> Foos
{
get
{
return foos.Select(x =>
new KeyValuePair<string, IEnumerable<string>>(x.Key, x.Value));
}
}
¿Hay una manera mejor / más limpia?
Desafortunadamente, KeyValuePair<TKey, TValue>
es una estructura; y las estructuras no muestran variación en .NET.
Por supuesto, puede resolver esto escribiendo su propia interfaz de Pair
covariante y algunos ayudantes simples para convertir secuencias de KeyValuePair
y su interfaz personalizada de Pair
. Esto te permitirá hacer:
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>>();
Aquí hay un código de ejemplo que te permitirá lograr esto:
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;
}
}