2009-06-10 17 views

Respuesta

5

Si sus "nombres" se determinan fácilmente a partir de su "T", sugiero KeyedCollection.

Funciona como List, en el que puede buscar elementos por índice. Pero también funciona como un diccionario, ya que utiliza un diccionario internamente para asignar nombres (claves) al índice apropiado y proporciona un indexador para su tipo de clave.


Ha preguntado cómo sabe qué usar para la clave. KeyedCollection es una clase abstracta que debe heredar. Afortunadamente, es fácil de hacer. El único método que debe sobrecargar es GetKeyForItem(). Ese método es la respuesta a tu pregunta. Por ejemplo, tomar esta clase simple:

Public Class MyClass 
    Public UniqueID As Guid 
    Public OtherData As String 
End Class 

podría implementar KeyedCollection así:

Public Class MyClassCollection 
    Inherits KeyedCollection(Of Guid, MyClass) 

    Public Overrides Function GetKeyForItem(ByVal item As MyClass) As Guid 
     Return item.UniqueID 
    End Function 
End Class 

Eso es todo lo que hay que hacer. Ahora tiene una colección que funcionará como un diccionario o una lista. Es aún más poderoso cuando puedes usar genéricos u otras interfaces para evitar vincular la clase a un tipo específico.

+0

¿cómo determina qué propiedad o campo en el objeto sería la clave? – Maslow

+0

'KeyedCollection' es una clase abstracta que debe heredar. Afortunadamente, es fácil de hacer. El único método que debes sobrecargar es 'GetKeyForItem()'. Ese método es la respuesta a tu pregunta. –

+0

Impresionante, creo que esto funcionará. – Maslow

-1

creo que busca System.Collections.Hashtable :)

+0

Nº tabla hash es básicamente la forma de pre-genérica de un diccionario . Maslow (creo) se busca un diccionario indexable, que no existe en el marco central. –

+0

Dale un golpe. Eso es lo que iba a decir. – ryanulit

+0

No veo una forma de indexar eso por entero, y no es genérico. Desde mi comprensión de los hashtables, pensé que una tabla hash debería ser exactamente lo que quería, pero hasta ahora lo que he explorado de System.Collections.Hashtable es la falta de indexación y tipo de seguridad. – Maslow

7

creo System.Collections.Specialized.OrderedDictionary es lo que estás buscando.

+0

Este es un tipo de multimapa de caso especial; Lástima que el BCL no tiene un propósito general. – Charlie

+0

OrderedDictionary te permitirá indexar por entero u Objeto ¿aparece? No me gusta lidiar con el boxeo/unboxing de lanzamiento constante, pero supongo que podría funcionar en algunos casos. – Maslow

+0

OrderedDictionary le permite usar un índice entero o una clave * object *. Es más antiguo que los genéricos, por lo que tanto la clave como el valor son tipos de objetos. Puede usar un par de diccionarios (un diccionario para índices y un diccionario para las claves) y mantenerlos sincronizados manualmente. Sin embargo, me conformaría con OrderedDictionary y el boxeo;) –

-1

Está accediendo a una lista de T por índice (Lista < Lista < T >>) ¿es lo suficientemente bueno?

List<List<foo>> list = new List<List<foo>>(); 
List<foo> firstList = list[0]; 
+0

que no parece permitirme hacer referencia a un foo por nombre/cadena. – Maslow

+0

Quizás respondí demasiado literalmente? Almacena listas (no matrices, por lo tanto, pregunto si eso fue suficiente) y le permite obtener una lista en un "índice" específico (numérico). Cuando dijiste "índice o nombre", lo interpreté como "int o string". Supongo que fue un error. – lance

+0

no, quiero una lista de T referenciada por int o cadena. pero una lista de la lista de T no sería indexable por cadena, eso es un nivel 2 int? – Maslow

0

Parece que necesita un multimapa, pero desafortunadamente no hay una implementación de este propósito en el BCL. Como se menciona en otra respuesta, System.Collections.Specialized.OrderedDictionary es una implementación específica que podría cubrir sus necesidades, aunque no utiliza genéricos.

1

La versión especializada de OrderedDictionary no es genérica.

Puede implementar una interfaz de Diccionario genérico con una clase GenericOrderedDictionary personalizada.

Tiene un privado

List<TKey>
y privado
List<TValue>
.

Visual Studio puede resguardar los métodos de interfaz para usted.

El inicio de la misma se vería así:


public class GenericOrderedDictionary< TKey, TValue > 
    : IDictionary<TKey, TValue> 
{ 
    private List<TKey> keys; 
    private List<TValue> values; 

    #region IDictionary<TKey,TValue> Members 

    void IDictionary<TKey, TValue>.Add(TKey key, TValue value) 
    { 
     keys.Add(key); 
     values.Add(value); 
    } 

    bool IDictionary<TKey, TValue>.ContainsKey(TKey key) 
    { 
     return keys.Contains(key); 
    } 

    ICollection<TKey> IDictionary<TKey, TValue>.Keys 
    { 
     get 
     { 
      return new List<TKey>(keys); 
     } 
    } 

    bool IDictionary<TKey, TValue>.Remove(TKey key) 
    { 
     int index = keys.IndexOf(key); 
     if (index >= 0) 
     { 
      keys.Remove(key); 
      values.RemoveAt(index); 
     } 
    } 

0

Si tiene una matriz de T, que puede generar múltiples diccionarios de esta matriz llamando ToDictionary y alimentación en diferentes propiedades de T.

suponiendo que T es el cliente:

Customer[] myCustomers = getArray(); 
Dictionary<int, Customer> byID = myCustomers 
    .ToDictionary(c => c.ID); 
Dictionary<string, Customer> byName = myCustomers 
    .ToDictionary(c => c.Name); 
Dictionary<int, Customer> byOriginalPosition = myCustomers 
    .Select((c, i) => new {c, i}) 
    .ToDictionary(x => x.i, x => x.c); 
2

creo que algo como esto está más cerca de lo que quiere:

class IndexDictionary<TKey, TValue> : Dictionary<TKey, TValue> 
    { 
    public TValue this[int i] 
    { 
     get { return this[Keys.ElementAt(i)]; } 
     set { this[Keys.ElementAt(i)] = value; } 
    } 
    } 

Estás tomando un diccionario regular <> y agregando la capacidad de indexar también por int.

Editar: Mehrdad plantea un buen punto, que mi método IndexDictionary.Add(TKey, TValue) puede resultar en un inserto en lugar de un anexar. Si eso va a causar problemas en su situación, entonces sugeriría algo como esto:

class OrderedDictionary<TKey, TValue> : IDictionary<TKey, TValue> 
    { 
    private OrderedDictionary data = new OrderedDictionary(); 

    public TValue this[int i] 
    { 
     get { return (TValue)data[i]; } 
     set { data[i] = value; } 
    } 

    //Implement IDictionary<TKey, TValue> using the methods of the OrderedDictionary 
    } 

Esto le da los beneficios de orden de preservación de la seguridad con OrderedDictionary tipo de Dictionary<TKey, TValue>.

+0

Sin embargo, el orden de las claves no está garantizado. Pueden cambiar a medida que se agregan o eliminan nuevos elementos. –

0

Esto es lo que estoy probando ahora la mayoría de la funcionalidad estaba en autocumplimentada para mí cuando he implementado IDictionary

Public Class bDictionary(Of TKey, TVAlue) 
Implements IDictionary(Of TKey, TVAlue) 

Private dictionary As New Dictionary(Of TKey, TVAlue) 
Private list As List(Of TKey) 

Default Public Property Item(ByVal which As TKey) As TVAlue Implements System.Collections.Generic.IDictionary(Of TKey, TVAlue).Item 
    Get 
     Return dictionary(which) 
    End Get 
    Set(ByVal value As TVAlue) 
     dictionary(which) = value 
    End Set 
End Property 

Default Public Property Item(ByVal index As Integer) As TVAlue 
    Get 
     Return dictionary(list(index)) 
    End Get 
    Set(ByVal value As TVAlue) 
     dictionary(list(index)) = value 
    End Set 
End Property 

Public Sub Add(ByVal key As TKey, ByVal value As TVAlue) Implements System.Collections.Generic.IDictionary(Of TKey, TVAlue).Add 
    dictionary.Add(key, value) 
    list.Add(key) 
End Sub 

Public Sub Add(ByVal item As System.Collections.Generic.KeyValuePair(Of TKey, TVAlue)) Implements System.Collections.Generic.ICollection(Of System.Collections.Generic.KeyValuePair(Of TKey, TVAlue)).Add 
    Add(item.Key, item.Value) 
End Sub 

Public Sub Clear() Implements System.Collections.Generic.ICollection(Of System.Collections.Generic.KeyValuePair(Of TKey, TVAlue)).Clear 
    dictionary.Clear() 
    list.Clear() 
End Sub 

Public Function Contains(ByVal item As System.Collections.Generic.KeyValuePair(Of TKey, TVAlue)) As Boolean Implements System.Collections.Generic.ICollection(Of System.Collections.Generic.KeyValuePair(Of TKey, TVAlue)).Contains 
    If dictionary.ContainsKey(item.Key) AndAlso dictionary(item.Key).Equals(item.Value) Then 
     Return True 
    Else 
     Return False 
    End If 

End Function 


Public ReadOnly Property Count() As Integer Implements System.Collections.Generic.ICollection(Of System.Collections.Generic.KeyValuePair(Of TKey, TVAlue)).Count 
    Get 
     Return list.Count 
    End Get 
End Property 

Public ReadOnly Property IsReadOnly() As Boolean Implements System.Collections.Generic.ICollection(Of System.Collections.Generic.KeyValuePair(Of TKey, TVAlue)).IsReadOnly 
    Get 
     Return False 
    End Get 
End Property 

Public Function Remove(ByVal item As System.Collections.Generic.KeyValuePair(Of TKey, TVAlue)) As Boolean Implements System.Collections.Generic.ICollection(Of System.Collections.Generic.KeyValuePair(Of TKey, TVAlue)).Remove 
    Return Remove(item.Key) 
End Function 

Public Function ContainsKey(ByVal key As TKey) As Boolean Implements System.Collections.Generic.IDictionary(Of TKey, TVAlue).ContainsKey 
    Return list.Contains(key) 
End Function 

Public ReadOnly Property Keys() As System.Collections.Generic.ICollection(Of TKey) Implements System.Collections.Generic.IDictionary(Of TKey, TVAlue).Keys 
    Get 
     Return dictionary.Keys 
    End Get 
End Property 

Public Function Remove(ByVal key As TKey) As Boolean Implements System.Collections.Generic.IDictionary(Of TKey, TVAlue).Remove 
    If list.Contains(key) Then 
     list.Remove(key) 
     dictionary.Remove(key) 
     Return True 
    Else 
     Return False 
    End If 
End Function 

Public Function TryGetValue(ByVal key As TKey, ByRef value As TVAlue) As Boolean Implements System.Collections.Generic.IDictionary(Of TKey, TVAlue).TryGetValue 
    Return dictionary.TryGetValue(key, value) 
End Function 

Public ReadOnly Property Values() As System.Collections.Generic.ICollection(Of TVAlue) Implements System.Collections.Generic.IDictionary(Of TKey, TVAlue).Values 
    Get 
     Return dictionary.Values 
    End Get 
End Property 


Public Sub CopyTo(ByVal array() As System.Collections.Generic.KeyValuePair(Of TKey, TVAlue), ByVal arrayIndex As Integer) Implements System.Collections.Generic.ICollection(Of System.Collections.Generic.KeyValuePair(Of TKey, TVAlue)).CopyTo 

    For Each Item As TKey In dictionary.Keys 
     array.SetValue(New KeyValuePair(Of TKey, TVAlue)(Item, dictionary(Item)), arrayIndex) 
     arrayIndex += 1 
    Next 

End Sub 

Public Function GetEnumerator() As System.Collections.IEnumerator Implements System.Collections.IEnumerable.GetEnumerator 
    Return dictionary.GetEnumerator() 
End Function 

Public Function GetEnumerator1() As System.Collections.Generic.IEnumerator(Of System.Collections.Generic.KeyValuePair(Of TKey, TVAlue)) Implements System.Collections.Generic.IEnumerable(Of System.Collections.Generic.KeyValuePair(Of TKey, TVAlue)).GetEnumerator 
    Return dictionary.GetEnumerator 
End Function 

End Class

Cuestiones relacionadas