2010-03-02 8 views
19

¿Cómo declaro una nueva clase de búsqueda para una propiedad en la rutina de inicialización de objetos en C#?Inicializando la búsqueda <int, string>

E.g.

new Component() { ID = 1, Name = "MOBO", Category = new Lookup<int, string> } 

La categoría bit siempre obtiene un error de compilación.


que tienen una propiedad llamada Category que es del tipo Lookup<int, string> y quiero crear una instancia de esta propiedad a través de

new Component() { ID = 1, Name = "MOBO", Category = new Lookup<int, string> }; 

pero no puedo conseguir más allá de los errores de compilación.

+0

Realmente no puedo seguir lo que estás tratando de hacer aquí ... ¿Tal vez añadir un poco más de información? – Stormenet

+0

Tan triste que las búsquedas no tienen un constructor. Me gustan mucho más que Dictionary porque la propiedad Key se deriva del objeto value. Mucho más DRY que un diccionario en el que constantemente debes contarlo una y otra vez. La Person.SSN es la clave cada vez que agregas un elemento. – AaronLS

+0

@AaronLS Supongo que te encantará [KeyedCollection] (https://msdn.microsoft.com/en-us/library/ms132438%28v=vs.110%29.aspx) ¡entonces! :) Todo lo que tiene que hacer es heredar de él e implementar el método que le indique cómo recuperar la clave del valor. (Es un método que toma un valor como entrada y devuelve la clave desde allí) ...Sin embargo, ten en cuenta que tiene algunas trampas y caprichos: recomiendo leer sobre él y hacer algunas pruebas antes de usarlo en serio. – AnorZaken

Respuesta

7

De MSDN:

No hay constructor público para crear una nueva instancia de un Lookup<TKey, TElement>.
Además, los objetos Lookup<TKey, TElement> son inmutables, es decir, no se pueden agregar o eliminar elementos o claves de un objeto Lookup<TKey, TElement> después de que se haya creado.

16

por documentación de MSDN, no hay ningún constructor público para la clase Lookup: http://msdn.microsoft.com/en-us/library/bb460184.aspx

puede crear una instancia de un Lookup<TKey, TElement> llamando ToLookup sobre un objeto que implementa IEnumerable<T>.

Usted tendrá que hacer algo como:

new Component { ID = 1, Name = "MOBO", Category = new[] { … }.ToLookup(…) } 

actualización para resolver los comentarios:

No estoy seguro de donde está recibiendo su categoría de información, por lo que va a hacer algo ...

new Component { 
    ID = 1, 
    Name = "MOBO", 
    Category = new Dictionary<int, string> { 
     { 3, "Beverages" } 
     { 5, "Produce" } 
    }.ToLookup(o => o.Key, o => o.Value) 
} 

Supongo que sus categorías vendrán de alguna otra fuente en lugar de crear un diccionario como lo hice aquí.

+0

Intenté esto, pero no te confundas, ¿qué se supone que está en las ... porciones? – Hannah

1

No puede usar ToLookup; usted tiene que decirle cómo encontrar las claves y valores:

// from ChaosPandion's code 
using System.Linq; // make sure you have the using statement 

var component = new Component() 
{ 
    ID = 1, 
    Name = "MOBO", 
    Category = (Lookup<int, string>) 
     (new Dictionary<int, string>() { {1, "one"} }) 
     .ToLookup(p=>p.Key, p=>p.Value) 
} 

No entiendo por qué desea utilizar una búsqueda aquí en lugar de un diccionario, sin embargo.

+2

Las búsquedas pueden contener claves duplicadas y mantener el orden. Esto es claramente diferente de un diccionario. Además, todo lo inmutable a un lado, por lo que si bien hay * algunas * implementaciones de mapas equivalentes ... no es un Diccionario. – user2864740

+0

@Gabe quiere usar 1 a Many mapping of lookup que no es posible en el diccionario –

1

Aquí está mi intento de esto. Asegúrese de que la clave sea inmutable (Gist).

public class MultiValueDictionary<TKey, TElement> 
: Collection<TElement>, ILookup<TKey, TElement> 
{ 
    public MultiValueDictionary(Func<TElement, TKey> keyForItem) 
    : base(new Collection(keyForItem)) 
    { 
    } 

    new Collection Items => (Collection)base.Items; 

    public IEnumerable<TElement> this[TKey key] => Items[key]; 
    public bool Contains(TKey key) => Items.Contains(key); 
    IEnumerator<IGrouping<TKey, TElement>> 
    IEnumerable<IGrouping<TKey, TElement>>.GetEnumerator() => Items.GetEnumerator(); 

    class Collection 
    : KeyedCollection<TKey, Grouping>, IEnumerable<TElement>, IList<TElement> 
    { 
    Func<TElement, TKey> KeyForItem { get; } 

    public Collection(Func<TElement, TKey> keyForItem) => KeyForItem = keyForItem; 
    protected override TKey GetKeyForItem(Grouping item) => item.Key; 

    public void Add(TElement item) 
    { 
     var key = KeyForItem(item); 
     if (Dictionary != null && Dictionary.TryGetValue(key, out var collection)) 
     collection.Add(item); 
     else 
     Add(new Grouping(key) { item }); 
    } 

    public bool Remove(TElement item) 
    { 
     var key = KeyForItem(item); 
     if (Dictionary != null && Dictionary.TryGetValue(key, out var collection) 
     && collection.Remove(item)) 
     { 
     if (collection.Count == 0) 
      Remove(key); 
     return true; 
     } 
     return false; 
    } 

    IEnumerator<TElement> IEnumerable<TElement>.GetEnumerator() 
    { 
     foreach (var group in base.Items) 
     foreach (var item in group) 
      yield return item; 
    } 

    const string IndexError = "Indexing not supported."; 
    public int IndexOf(TElement item) => throw new NotSupportedException(IndexError); 
    public void Insert(int index, TElement item) => Add(item); 
    public bool Contains(TElement item) => Items.Contains(item); 
    public void CopyTo(TElement[] array, int arrayIndex) => 
    throw new NotSupportedException(IndexError); 
    new IEnumerable<TElement> Items => this; 
    public bool IsReadOnly => false; 
    TElement IList<TElement>.this[int index] 
    { 
     get => throw new NotSupportedException(IndexError); 
     set => throw new NotSupportedException(IndexError); 
    } 
    } 

    class Grouping : Collection<TElement>, IGrouping<TKey, TElement> 
    { 
    public Grouping(TKey key) => Key = key; 
    public TKey Key { get; } 
    } 
} 
Cuestiones relacionadas