2013-08-27 6 views
6

Vorrei essere in grado di eseguire una query LINQ su un BindingList (Of T) che restituisce gli indici in cui un membro dell'oggetto elenco è uguale a un valore particolare.Ottenere l'indice del valore corrispondente in Elenco utilizzando LINQ

dire che ho una lista di semplici oggetti di widget di classe:

Public Class widget 
    Public Property foo As Integer 
    Public Property bar As String 
End Class 
Dim widgetList As BindingList(Of widget) 

mi piacerebbe essere in grado di interrogare l'elenco qualche cosa come il qui sotto:

Dim test As Integer = 5 
Dim index = (From i In widgetList 
      Where i.foo = test 
      Select i.index).First 

Tale quell'indice contiene l'indice del primo listItem dove widgetList.Item (index) .foo = 5. Qual è il modo migliore per farlo? (O dovrei anche essere utilizzando LINQ)

Ho visto diversi metodi C# per fare questo, ma io non sono sufficientemente au fait con C# per capire come usarli in VB

+0

Per quanto riguarda il linq, la sintassi C# e vb sono quasi sempre le stesse. Riguardo alla tua domanda: nel titolo ti stai chiedendo di abbinare valueS (significa che ti stai aspettando più di una corrispondenza) ma nel codice che stai utilizzando. Primo, il che significa che stai prendendo solo il primo oggetto dai risultati selezionati. –

+0

Così ho fatto - modificato per rimuovere plurale. Grazie – Toby

risposta

6

E 'possibile ottenere con LINQ utilizzando la sintassi fluente poiché esiste una versione sovraccaricata del metodo di estensione Select che consente di ottenere l'indice degli articoli.

Prova questo approccio:

Dim test As Integer = 5 
Dim query = widgetList.Select(Function(o,i) New With { .Widget = o, .Index = i}) _ 
         .FirstOrDefault(Function(item) item.Widget.Foo = test) 
If query Is Nothing 
    Console.WriteLine("Item not found") 
Else 
    Console.WriteLine("Item found at index {0}", query.Index) 
End If 

Nel Select sto proiettando il widget come è, utilizzando o, e il parametro i rappresenta l'indice. Successivamente io uso FirstOrDefault con un predicato per valutare Foo (potresti aver usato Where seguito da FirstOrDefault, ma questo è più breve). È necessario utilizzare FirstOrDefault anziché solo First nel caso in cui nessuno degli elementi venga trovato; FirstOrDefault restituirà null se non viene trovato nulla, mentre First genererebbe un'eccezione. Ecco perché il prossimo passo è controllare il risultato e accertarsi che non sia nullo.

1

Ho anche trovato una soluzione funzionante come di seguito, anche se non sono sicuro che sia meglio o peggio delle altre risposte.

Dim index = Enumerable.Range(0, widgetList.Count) _ 
      .Where(Function(i) widgetList.Item(i).foo = test) _ 
      .First 
+1

Funziona ma hai introdotto una nuova raccolta da confrontare con la tua collezione originale, che * probabilmente * si comporta più lentamente. Dal punto di vista della leggibilità, è più chiaro lavorare contro la collezione originale. Dal punto di vista delle prestazioni, il codice deve generare elementi 'n' nell'intervallo per valutare la query. –

+0

@AhmadMageed, buon uomo, grazie, passerò alla tua risposta quindi :) – Toby

Problemi correlati