varianza positiva finanzas definicion covarianza correlacion como calcular c# .net dictionary readonly covariance

c# - positiva - covarianza y correlacion



¿Cómo evitar la falta de covarianza con IReadOnlyDictionary? (5)

Dependiendo de su caso de uso, puede salirse con la exposición de un Func<int,IReadOnly> .

public class ExposesReadOnly { private Dictionary<int, NotReadOnly> InternalDict { get; set; } public Func<int,IReadOnly> PublicDictionaryAccess { get { return (x)=>this.InternalDict[x]; } } // This class can be modified internally, but I don''t want // to expose this functionality. private class NotReadOnly : IReadOnly { public string Name { get; set; } } } public interface IReadOnly { string Name { get; } }

Estoy intentando exponer un diccionario de solo lectura que contiene objetos con una interfaz de solo lectura. Internamente, el diccionario se puede escribir, y también lo son los objetos que están dentro (vea el código de ejemplo a continuación). Mi problema es que IReadOnlyDictionary no admite conversiones covariantes debido a la razón descrita en la pregunta here . Esto significa que no puedo exponer mi diccionario interno como solo lectura.

Entonces, mi pregunta es, ¿existe una manera eficiente de convertir mi diccionario interno a un IReadOnlyDictionary, o alguna otra forma de manejar esto? Las opciones que se me ocurren son:

  1. Mantenga dos diccionarios internos y manténgalos sincronizados.
  2. Cree un nuevo diccionario cuando se acceda a la propiedad y lance todos los objetos que contiene.
  3. Vuelva a colocar el IReadOnly en NotReadOnly cuando lo use internamente.

1 parece un dolor, 2 parece altamente ineficiente. 3 suena como el más prometedor en este momento, pero sigue siendo feo. ¿Tengo otras opciones?

public class ExposesReadOnly { private Dictionary<int, NotReadOnly> InternalDict { get; set; } public IReadOnlyDictionary<int, IReadOnly> PublicList { get { // This doesn''t work... return this.InternalDict; } } // This class can be modified internally, but I don''t want // to expose this functionality. private class NotReadOnly : IReadOnly { public string Name { get; set; } } } public interface IReadOnly { string Name { get; } }


Le sugiero que desee definir sus propias interfaces covariantes e incluir métodos de acceso covariante, así como un método que creará un objeto de contenedor de solo lectura que implemente IDictionary o IReadonlyDictionary con los tipos deseados. Simplemente ignore IEnumerable<KeyValuePair<TKey,TValue>> dentro de su interfaz.

Dependiendo de lo que esté haciendo, puede ser útil definir un IFetchByKey<out TValue> que es heredado por IFetchByKey<in TKey, out TValue> , con las primeras consultas de aceptación para cualquier tipo de objeto (dada una instancia de objeto, una la colección de Cat debería poder decir si contiene esa instancia, incluso si es un tipo Dog o ToyotaPrius ; la colección no contendrá ninguna instancia de los últimos tipos, y debería poder decirlo).


Otro enfoque para una falta específica de covarianza:

Un trabajo alrededor de un tipo específico de covarianza útil en idictionary

public static class DictionaryExtensions { public static IReadOnlyDictionary<TKey, IEnumerable<TValue>> ToReadOnlyDictionary<TKey, TValue>( this IDictionary<TKey, List<TValue>> toWrap) { var intermediate = toWrap.ToDictionary(a => a.Key, a =>a.Value!=null? a.Value.ToArray().AsEnumerable():null); var wrapper = new ReadOnlyDictionary<TKey, IEnumerable<TValue>>(intermediate); return wrapper; } }


Puede escribir su propio contenedor de solo lectura para el diccionario, por ejemplo:

public class ReadOnlyDictionaryWrapper<TKey, TValue, TReadOnlyValue> : IReadOnlyDictionary<TKey, TReadOnlyValue> where TValue : TReadOnlyValue { private IDictionary<TKey, TValue> _dictionary; public ReadOnlyDictionaryWrapper(IDictionary<TKey, TValue> dictionary) { if (dictionary == null) throw new ArgumentNullException("dictionary"); _dictionary = dictionary; } public bool ContainsKey(TKey key) { return _dictionary.ContainsKey(key); } public IEnumerable<TKey> Keys { get { return _dictionary.Keys; } } public bool TryGetValue(TKey key, out TReadOnlyValue value) { TValue v; var result = _dictionary.TryGetValue(key, out v); value = v; return result; } public IEnumerable<TReadOnlyValue> Values { get { return _dictionary.Values.Cast<TReadOnlyValue>(); } } public TReadOnlyValue this[TKey key] { get { return _dictionary[key]; } } public int Count { get { return _dictionary.Count; } } public IEnumerator<KeyValuePair<TKey, TReadOnlyValue>> GetEnumerator() { return _dictionary .Select(x => new KeyValuePair<TKey, TReadOnlyValue>(x.Key, x.Value)) .GetEnumerator(); } System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { return this.GetEnumerator(); } }


Tal vez esta solución funcione para usted:

public class ExposesReadOnly { private IDictionary<int, IReadOnly> InternalDict { get; set; } public IReadOnlyDictionary<int, IReadOnly> PublicList { get { IReadOnlyDictionary<int, IReadOnly> dictionary = new ReadOnlyDictionary<int, IReadOnly>(InternalDict); return dictionary; } } private class NotReadOnly : IReadOnly { public string Name { get; set; } } public void AddSomeValue() { InternalDict = new Dictionary<int, NotReadOnly>(); InternalDict.Add(1, new NotReadOnly() { Name = "SomeValue" }); } } public interface IReadOnly { string Name { get; } } class Program { static void Main(string[] args) { ExposesReadOnly exposesReadOnly = new ExposesReadOnly(); exposesReadOnly.AddSomeValue(); Console.WriteLine(exposesReadOnly.PublicList[1].Name); Console.ReadLine(); exposesReadOnly.PublicList[1].Name = "This is not possible!"; } }

¡Espero que esto ayude!

Saludos