Come si fa a trovare l'ultimo ciclo in un For Each (VB.NET)?
Domanda
Come è possibile determinare se sono nel ciclo finale di una per ogni istruzione in VB.NET?
Soluzione
Il generale, raccolte su cui è possibile eseguire For Each
sul implementare il IEnumerator
interfaccia. Questa interfaccia ha solo due metodi, MoveNext
e Reset
e una proprietà, Current
.
In sostanza, quando si utilizza un For Each
su una collezione, si chiama la funzione MoveNext
e legge il valore restituito. Se il valore restituito è True
, significa che c'è un elemento valido nella raccolta e l'elemento viene restituito tramite la proprietà Current
. Se non ci sono più elementi della collezione, la funzione restituisce MoveNext
False
e l'iterazione si esce.
Da quanto sopra esposto, è chiaro che il For Each
non tiene la posizione attuale nella raccolta e quindi la risposta alla tua domanda è un breve No .
Se, tuttavia, è ancora il desiderio di sapere se sei l'ultimo elemento nella vostra collezione, è possibile provare il seguente codice. Esso controlla (utilizzando LINQ) se l'elemento corrente è l'ultimo elemento.
For Each item in Collection
If item Is Collection.Last Then
'do something with your last item'
End If
Next
Altri suggerimenti
Probabilmente sarebbe stato più facile usare solo un ciclo For invece di ForEach. Ma, allo stesso modo, si potrebbe tenere un contatore all'interno del vostro ciclo ForEach e vedere se il suo pari a yourCollection.Count - 1
, allora siete nel l'ultima iterazione.
Con un foreach, non puoi sapere questo fino a quando non è troppo tardi (es. Sei fuori dal giro).
Nota, sto supponendo che si sta utilizzando qualcosa in cui si ha solo un'interfaccia IEnumerable. Se si dispone di un elenco, array, ecc quindi seguire le altre risposte qui che utilizza Count o simile per scoprire quanti oggetti ci sono, e quindi si può tenere traccia di dove ci si trova nella collezione.
Tuttavia, con solo IEnumerable / IEnumerator, non c'è modo di sapere con certezza montone castrato o no ci sono più, se si utilizza foreach.
Se avete bisogno di sapere questo, utilizzare IEnumerable te stesso, che è ciò che fa foreach.
La soluzione qui di seguito è per C #, ma dovrebbe tradursi facilmente in VB.NET:
List<Int32> nums = new List<Int32>();
nums.Add(1);
nums.Add(2);
nums.Add(3);
IEnumerator<Int32> enumerator = nums.GetEnumerator();
if (enumerator.MoveNext())
{
// at least one value available
while (true)
{
// make a copy of it
Int32 current = enumerator.Current;
// determine if it was the last value
// if not, enumerator.Current is now the next value
if (enumerator.MoveNext())
{
Console.Out.WriteLine("not last: " + current);
}
else
{
Console.Out.WriteLine("last: " + current);
break;
}
}
}
enumerator.Dispose();
Questa stampa volontà:
not last: 1
not last: 2
last: 3
Il trucco è quello di prendere una copia del valore corrente, poi chiedere l'enumeratore per tentare di passare a quello successivo. Se non funziona, la copia che hai fatto era davvero l'ultimo valore, altrimenti non c'è più.
Risposta breve: non è possibile
Risposta lunga: Non c'è niente nella semantica di una per ogni istruzione che permette di identificare se si sta eseguendo il primo, ultimo o una particolare iterazione.
Per ogni è costruito nel IEnumerable e IEnumerable <> interfacce, e il comportamento dipende dalla realizzazione si sta chiamando. E 'valida, anche se confusa, per la raccolta si sta iterazione di restituire gli elementi in un ordine diverso ogni volta. Fortunatamente, List <> non fa questo.
Se avete veramente bisogno di sapere che una particolare iterazione è l'ultimo, si potrebbe identificare l'ultimo elemento (in anticipo) e poi agire diverso quando si incontra questo elemento.
Più facile sarebbe quella di rilevare il prima iterazione (ad esempio, attraverso un valore booleano) e poi fare qualcosa di diverso.
Un esempio (C #, ma il VB saranno simili):
StringBuilder result = new StringBuilder();
bool firstTime = true;
foreach(string s in names)
{
if (!firstTime)
{
result.Append(", ");
}
result.Append(s);
firstTime = false;
}
Controlla se l'elemento è l'ultimo elemento del contenitore.
Perché vuoi farlo?
Si potrebbe semplicemente inserire le istruzioni dopo il ciclo. (Che si esegue l'ultimo elemento)
Sarebbe più facile da utilizzare un ciclo For invece di un ForEach, tuttavia si potrebbe fare qualcosa di simile
If item.Equals(itemCollection(itemCollection.Count)) Then
...
End If
all'interno del vostro ciclo ForEach ... Supponendo che l'oggetto ha correttamente ignorato il metodo Equals.
Questo è probabilmente molto più risorse rispetto solo utilizzando un ciclo For o tenere traccia dell'indice corrente in una variabile separata.
Non sono sicuro se questa è la sintassi corretta, è passato molto tempo da quando ho usato VB.
Utilizzo di uno standard "per ogni" ciclo non si può. L'intento di un "per ogni" ciclo è quello di permettere di concentrarsi sui dati al posto della collezione sottostante.
Continuo a tornare a questo post, così ho deciso di sedermi e pensare a questo problema e mi si avvicinò con questo:
For Each obj In myCollection
Console.WriteLine("current object: {0}", obj.ToString)
If Object.ReferenceEquals(obj, myCollection.Last()) Then
Console.WriteLine("current object is the last object")
End If
Next
Si potrebbe anche ridurre la dichiarazione If...Then...End If
a una singola linea se si voleva. Io non sono sicuro se chiamare .Last()
ad ogni iterazione ha un grande impatto sulle prestazioni, ma si può sempre assegnarlo a una variabile al di fuori del ciclo se è questo che ti tiene sveglio la notte.
questo esempio di codice potrebbe aiutare
For Each item in Collection
If ReferenceEquals(Collection.Item(Collection.Count - 1), item) Then
'do something with your last item'
End If
Next
Se si sono legati a IEnumerable. Dovete essere all'interno del ciclo foreach? Se non si poteva dichiarare una variabile poco prima del ciclo foreach. Impostare durante il ciclo. Quindi, utilizzare dopo il ciclo (se non nullo)
Beh ci sono pochi soluzione Supponiamo che si sta lavorando con CheckBoxList
Quindi questo esempio di codice potrebbe aiutare:
Dim count As Integer = 0
Dim totalListCount As Integer = CheckBoxList.Items.Count()
For Each li In CheckBoxList.Items
count += 1
// This is the Last Item
If count = totalListCount THEN
// DO Somthing.....
END IF
NEXT
qui è una cosa semplice non so se è politicamente corretto ma funziona
for each item in listOfThings
if(item = listOfThings.last)then
'you found the last loop
end if
next