Istruzione For Each...Next (Visual Basic)For Each...Next Statement (Visual Basic)

Ripete un gruppo di istruzioni per ogni elemento di una raccolta.Repeats a group of statements for each element in a collection.

SintassiSyntax

For Each element [ As datatype ] In group
    [ statements ]
    [ Continue For ]
    [ statements ]
    [ Exit For ]
    [ statements ]
Next [ element ]

PartiParts

TermineTerm DefinizioneDefinition
element Obbligatorio nell'istruzione For Each.Required in the For Each statement. Facoltativo nell'istruzione Next.Optional in the Next statement. Variabile.Variable. Utilizzato per scorrere gli elementi della raccolta.Used to iterate through the elements of the collection.
datatype Facoltativo se Option Infer è on (impostazione predefinita) o element è già dichiarato; obbligatorio se Option Infer è disattivato e element non è già stato dichiarato.Optional if Option Infer is on (the default) or element is already declared; required if Option Infer is off and element isn't already declared. Tipo di dati di element.The data type of element.
group Obbligatoria.Required. Una variabile con un tipo che è un tipo di raccolta o un oggetto.A variable with a type that's a collection type or Object. Fa riferimento alla raccolta in cui devono essere ripetute le statements.Refers to the collection over which the statements are to be repeated.
statements Facoltativa.Optional. Una o più istruzioni tra For Each e Next eseguite in ogni elemento in group.One or more statements between For Each and Next that run on each item in group.
Continue For Facoltativa.Optional. Trasferisce il controllo all'inizio del ciclo For Each.Transfers control to the start of the For Each loop.
Exit For Facoltativa.Optional. Trasferisce il controllo all'esterno del ciclo For Each.Transfers control out of the For Each loop.
Next Obbligatoria.Required. Termina la definizione del ciclo For Each.Terminates the definition of the For Each loop.

Esempio sempliceSimple Example

Utilizzare un ciclo For Each...Next quando si desidera ripetere un set di istruzioni per ogni elemento di una raccolta o di una matrice.Use a For Each...Next loop when you want to repeat a set of statements for each element of a collection or array.

Suggerimento

Oggetto per... L'istruzione successiva funziona bene quando è possibile associare ogni iterazione di un ciclo a una variabile di controllo e determinare i valori iniziale e finale della variabile.A For...Next Statement works well when you can associate each iteration of a loop with a control variable and determine that variable's initial and final values. Tuttavia, quando si tratta di una raccolta, il concetto di valori iniziali e finali non è significativo e non si conosce necessariamente il numero di elementi della raccolta.However, when you are dealing with a collection, the concept of initial and final values isn't meaningful, and you don't necessarily know how many elements the collection has. In questo tipo di caso, un ciclo For Each...Next è spesso una scelta migliore.In this kind of case, a For Each...Next loop is often a better choice.

Nell'esempio seguente, il For Each...NextIn the following example, the For EachNext l'istruzione scorre tutti gli elementi di una raccolta di elenchi.statement iterates through all the elements of a List collection.

' Create a list of strings by using a
' collection initializer.
Dim lst As New List(Of String) _
    From {"abc", "def", "ghi"}

' Iterate through the list.
For Each item As String In lst
    Debug.Write(item & " ")
Next
Debug.WriteLine("")
'Output: abc def ghi

Per altri esempi, vedere raccolte e matrici.For more examples, see Collections and Arrays.

Nested LoopsNested Loops

È possibile annidare For Each cicli inserendo un ciclo all'interno di un altro.You can nest For Each loops by putting one loop within another.

Nell'esempio seguente viene illustrata la For Eachannidata...NextThe following example demonstrates nested For EachNext Strutture.structures.

' Create lists of numbers and letters
' by using array initializers.
Dim numbers() As Integer = {1, 4, 7}
Dim letters() As String = {"a", "b", "c"}

' Iterate through the list by using nested loops.
For Each number As Integer In numbers
    For Each letter As String In letters
        Debug.Write(number.ToString & letter & " ")
    Next
Next
Debug.WriteLine("")
'Output: 1a 1b 1c 4a 4b 4c 7a 7b 7c 

Quando si annidano i cicli, ogni ciclo deve avere una variabile element univoca.When you nest loops, each loop must have a unique element variable.

È anche possibile annidare diversi tipi di strutture di controllo tra loro.You can also nest different kinds of control structures within each other. Per altre informazioni, vedere strutture di controlli annidati.For more information, see Nested Control Structures.

Esci per e continua perExit For and Continue For

L'istruzione Exit for causa l'uscita dall'esecuzione del For...NextThe Exit For statement causes execution to exit the ForNext esegue il ciclo e trasferisce il controllo all'istruzione che segue l'istruzione Next.loop and transfers control to the statement that follows the Next statement.

L'istruzione Continue For trasferisce immediatamente il controllo all'iterazione successiva del ciclo.The Continue For statement transfers control immediately to the next iteration of the loop. Per ulteriori informazioni, vedere istruzione continue.For more information, see Continue Statement.

Nell'esempio seguente viene illustrato come utilizzare le istruzioni Continue For e Exit For.The following example shows how to use the Continue For and Exit For statements.

Dim numberSeq() As Integer =
    {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}

For Each number As Integer In numberSeq
    ' If number is between 5 and 7, continue
    ' with the next iteration.
    If number >= 5 And number <= 8 Then
        Continue For
    End If

    ' Display the number.
    Debug.Write(number.ToString & " ")

    ' If number is 10, exit the loop.
    If number = 10 Then
        Exit For
    End If
Next
Debug.WriteLine("")
' Output: 1 2 3 4 9 10

È possibile inserire un numero qualsiasi di istruzioni Exit For in un ciclo di For Each.You can put any number of Exit For statements in a For Each loop. Quando viene usato all'interno di cicli di For Each annidati, Exit For fa sì che l'esecuzione esca dal ciclo più interno e trasferisce il controllo al successivo livello di nidificazione.When used within nested For Each loops, Exit For causes execution to exit the innermost loop and transfers control to the next higher level of nesting.

Exit For viene spesso utilizzato dopo una valutazione di una determinata condizione, ad esempio in una struttura If...Then...Else.Exit For is often used after an evaluation of some condition, for example, in an If...Then...Else structure. Potrebbe essere necessario utilizzare Exit For per le condizioni seguenti:You might want to use Exit For for the following conditions:

  • La continuazione dell'iterazione non è necessaria o impossibile.Continuing to iterate is unnecessary or impossible. Il problema potrebbe essere causato da un valore errato o da una richiesta di terminazione.This might be caused by an erroneous value or a termination request.

  • Un'eccezione viene rilevata in un Try...Catch...Finally. È possibile utilizzare Exit For alla fine del blocco di Finally.An exception is caught in a Try...Catch...Finally. You might use Exit For at the end of the Finally block.

  • Un ciclo infinito, ovvero un ciclo che può eseguire un numero di volte elevato o infinito.There an endless loop, which is a loop that could run a large or even infinite number of times. Se si rileva tale condizione, è possibile utilizzare Exit For per eseguire l'escape del ciclo.If you detect such a condition, you can use Exit For to escape the loop. Per ulteriori informazioni, vedere ... Istruzione Loop.For more information, see Do...Loop Statement.

IteratoriIterators

Si usa un iteratore per eseguire un'iterazione personalizzata su una raccolta.You use an iterator to perform a custom iteration over a collection. Un iteratore può essere una funzione o una funzione di accesso Get.An iterator can be a function or a Get accessor. Usa un'istruzione Yield per restituire ogni elemento della raccolta uno alla volta.It uses a Yield statement to return each element of the collection one at a time.

È possibile chiamare un iteratore usando un'istruzione For Each...Next.You call an iterator by using a For Each...Next statement. Ogni iterazione del ciclo For Each chiama l'iteratore.Each iteration of the For Each loop calls the iterator. Quando viene raggiunta un'istruzione Yield nell'iteratore, viene restituita l'espressione nell'istruzione Yield e viene mantenuta la posizione corrente nel codice.When a Yield statement is reached in the iterator, the expression in the Yield statement is returned, and the current location in code is retained. L'esecuzione viene ripresa a partire da quella posizione la volta successiva che viene chiamato l'iteratore.Execution is restarted from that location the next time that the iterator is called.

Nell'esempio seguente viene utilizzata una funzione iteratore.The following example uses an iterator function. La funzione iteratore dispone di un'istruzione Yield che si trova all'interno di un oggetto per... Ciclo successivo .The iterator function has a Yield statement that's inside a For…Next loop. Nel metodo ListEvenNumbers ogni iterazione del corpo dell'istruzione For Each crea una chiamata alla funzione iteratore, che procede all'istruzione Yield successiva.In the ListEvenNumbers method, each iteration of the For Each statement body creates a call to the iterator function, which proceeds to the next Yield statement.

Public Sub ListEvenNumbers()
    For Each number As Integer In EvenSequence(5, 18)
        Debug.Write(number & " ")
    Next
    Debug.WriteLine("")
    ' Output: 6 8 10 12 14 16 18
End Sub

Private Iterator Function EvenSequence(
ByVal firstNumber As Integer, ByVal lastNumber As Integer) _
As System.Collections.Generic.IEnumerable(Of Integer)

    ' Yield even numbers in the range.
    For number = firstNumber To lastNumber
        If number Mod 2 = 0 Then
            Yield number
        End If
    Next
End Function

Per ulteriori informazioni, vedere iteratori, istruzione yielde iteratore.For more information, see Iterators, Yield Statement, and Iterator.

Implementazione tecnicaTechnical Implementation

Quando un For Each...NextWhen a For EachNext l'istruzione viene eseguita, Visual Basic valuta la raccolta solo una volta, prima dell'avvio del ciclo.statement runs, Visual Basic evaluates the collection only one time, before the loop starts. Se il blocco di istruzioni cambia element o group, queste modifiche non influiscono sull'iterazione del ciclo.If your statement block changes element or group, these changes don't affect the iteration of the loop.

Quando tutti gli elementi della raccolta sono stati assegnati successivamente a element, il ciclo For Each si interrompe e il controllo passa all'istruzione che segue l'istruzione Next.When all the elements in the collection have been successively assigned to element, the For Each loop stops and control passes to the statement following the Next statement.

Se Option deduce è on (impostazione predefinita), il Visual Basic compilatore può dedurre il tipo di dati di element.If Option Infer is on (its default setting), the Visual Basic compiler can infer the data type of element. Se è disattivata e element non è stata dichiarata al di fuori del ciclo, è necessario dichiararla nell'istruzione For Each.If it is off and element hasn't been declared outside the loop, you must declare it in the For Each statement. Per dichiarare in modo esplicito il tipo di dati di element, utilizzare una clausola As.To declare the data type of element explicitly, use an As clause. A meno che il tipo di dati dell'elemento non sia definito al di fuori del costrutto For Each...Next, il relativo ambito è il corpo del ciclo.Unless the data type of element is defined outside the For Each...Next construct, its scope is the body of the loop. Si noti che non è possibile dichiarare element sia all'esterno che all'interno del ciclo.Note that you cannot declare element both outside and inside the loop.

Facoltativamente, è possibile specificare element nell'istruzione Next.You can optionally specify element in the Next statement. In questo modo è possibile migliorare la leggibilità del programma, soprattutto se sono presenti cicli di For Each annidati.This improves the readability of your program, especially if you have nested For Each loops. È necessario specificare la stessa variabile di quella visualizzata nell'istruzione For Each corrispondente.You must specify the same variable as the one that appears in the corresponding For Each statement.

È consigliabile evitare di modificare il valore di element all'interno di un ciclo.You might want to avoid changing the value of element inside a loop. Questa operazione può rendere più difficile la lettura e il debug del codice.Doing this can make it more difficult to read and debug your code. La modifica del valore di group non influisce sulla raccolta o sui relativi elementi, che sono stati determinati quando il ciclo è stato immesso per la prima volta.Changing the value of group doesn't affect the collection or its elements, which were determined when the loop was first entered.

Quando si annidano i cicli, se viene rilevata un'istruzione Next di un livello di nidificazione esterno prima del Next di un livello interno, il compilatore segnala un errore.When you're nesting loops, if a Next statement of an outer nesting level is encountered before the Next of an inner level, the compiler signals an error. Tuttavia, il compilatore può rilevare questo errore di sovrapposizione solo se si specifica element in ogni istruzione Next.However, the compiler can detect this overlapping error only if you specify element in every Next statement.

Se il codice dipende dall'attraversamento di una raccolta in un ordine particolare, un ciclo For Each...Next non è la scelta migliore, a meno che non si conoscano le caratteristiche dell'oggetto enumeratore esposto dalla raccolta.If your code depends on traversing a collection in a particular order, a For Each...Next loop isn't the best choice, unless you know the characteristics of the enumerator object the collection exposes. L'ordine di attraversamento non è determinato dal Visual Basic, ma dal metodo MoveNext dell'oggetto enumeratore.The order of traversal isn't determined by Visual Basic, but by the MoveNext method of the enumerator object. Pertanto, potrebbe non essere possibile stimare quale elemento della raccolta è il primo a essere restituito in elemento che è il successivo da restituire dopo un determinato elemento.Therefore, you might not be able to predict which element of the collection is the first to be returned in element, or which is the next to be returned after a given element. È possibile ottenere risultati più affidabili utilizzando una struttura di ciclo diversa, ad esempio For...Next o Do...Loop.You might achieve more reliable results using a different loop structure, such as For...Next or Do...Loop.

Il runtime deve essere in grado di convertire gli elementi in group element.The runtime must be able to convert the elements in group to element. L'istruzione [Option Strict] consente di controllare se sono consentite sia le conversioni verso un tipo di ingrandimento che quello più piccolo (Option Strict è disattivato, il valore predefinito) o se sono consentite solo conversioni verso un tipo di ingrandimento (Option Strict è on).The [Option Strict] statement controls whether both widening and narrowing conversions are allowed (Option Strict is off, its default value), or whether only widening conversions are allowed (Option Strict is on). Per altre informazioni, vedere conversioniverso un tipo di dati più piccolo.For more information, see Narrowing conversions.

Il tipo di dati di group deve essere un tipo di riferimento che fa riferimento a una raccolta o a una matrice enumerabile.The data type of group must be a reference type that refers to a collection or an array that's enumerable. In genere ciò significa che group fa riferimento a un oggetto che implementa l'interfaccia IEnumerable dello spazio dei nomi System.Collections o l'interfaccia IEnumerable<T> dello spazio dei nomi System.Collections.Generic.Most commonly this means that group refers to an object that implements the IEnumerable interface of the System.Collections namespace or the IEnumerable<T> interface of the System.Collections.Generic namespace. System.Collections.IEnumerable definisce il metodo GetEnumerator, che restituisce un oggetto enumeratore per la raccolta.System.Collections.IEnumerable defines the GetEnumerator method, which returns an enumerator object for the collection. L'oggetto enumeratore implementa l'interfaccia System.Collections.IEnumerator dello spazio dei nomi System.Collections ed espone la proprietà Current e i metodi Reset e MoveNext.The enumerator object implements the System.Collections.IEnumerator interface of the System.Collections namespace and exposes the Current property and the Reset and MoveNext methods. Visual Basic utilizza questi per attraversare la raccolta.Visual Basic uses these to traverse the collection.

conversioni verso un tipo di dati più piccoloNarrowing Conversions

Quando Option Strict è impostato su On, le conversioni verso un tipo di caratteri più piccolo generano generalmente errori del compilatore.When Option Strict is set to On, narrowing conversions ordinarily cause compiler errors. In un'istruzione For Each, tuttavia, le conversioni dagli elementi group a element vengono valutate e eseguite in fase di esecuzione e gli errori del compilatore causati da conversioni verso un tipo di caratteri più piccolo vengono eliminati.In a For Each statement, however, conversions from the elements in group to element are evaluated and performed at run time, and compiler errors caused by narrowing conversions are suppressed.

Nell'esempio seguente, l'assegnazione di m come valore iniziale per n non viene compilata quando Option Strict è impostata su on perché la conversione di un Long in un Integer è una conversione verso un tipo di caratteri più piccolo.In the following example, the assignment of m as the initial value for n doesn't compile when Option Strict is on because the conversion of a Long to an Integer is a narrowing conversion. Nell'istruzione For Each, tuttavia, non viene segnalato alcun errore del compilatore, anche se l'assegnazione a number richiede la stessa conversione da Long a Integer.In the For Each statement, however, no compiler error is reported, even though the assignment to number requires the same conversion from Long to Integer. Nell'istruzione For Each contenente un numero elevato, si verifica un errore di run-time quando ToInteger viene applicato al numero elevato.In the For Each statement that contains a large number, a run-time error occurs when ToInteger is applied to the large number.

Option Strict On

Module Module1
    Sub Main()
        ' The assignment of m to n causes a compiler error when 
        ' Option Strict is on.
        Dim m As Long = 987
        'Dim n As Integer = m

        ' The For Each loop requires the same conversion but
        ' causes no errors, even when Option Strict is on.
        For Each number As Integer In New Long() {45, 3, 987}
            Console.Write(number & " ")
        Next
        Console.WriteLine()
        ' Output: 45 3 987

        ' Here a run-time error is raised because 9876543210
        ' is too large for type Integer.
        'For Each number As Integer In New Long() {45, 3, 9876543210}
        '    Console.Write(number & " ")
        'Next

        Console.ReadKey()
    End Sub
End Module

Chiamate IEnumeratorIEnumerator Calls

Quando viene avviata l'esecuzione di un ciclo For Each...Next, Visual Basic verifica che group faccia riferimento a un oggetto raccolta valido.When execution of a For Each...Next loop starts, Visual Basic verifies that group refers to a valid collection object. In caso contrario, viene generata un'eccezione.If not, it throws an exception. In caso contrario, chiama il metodo MoveNext e la proprietà Current dell'oggetto enumeratore per restituire il primo elemento.Otherwise, it calls the MoveNext method and the Current property of the enumerator object to return the first element. Se MoveNext indica che non è presente alcun elemento successivo, ovvero se la raccolta è vuota, il ciclo di For Each si interrompe e il controllo passa all'istruzione che segue l'istruzione Next.If MoveNext indicates that there is no next element, that is, if the collection is empty, the For Each loop stops and control passes to the statement following the Next statement. In caso contrario, Visual Basic imposta element sul primo elemento ed esegue il blocco di istruzioni.Otherwise, Visual Basic sets element to the first element and runs the statement block.

Ogni volta che Visual Basic rileva l'istruzione Next, viene restituito all'istruzione For Each.Each time Visual Basic encounters the Next statement, it returns to the For Each statement. Chiama di nuovo MoveNext e Current per restituire l'elemento successivo, quindi esegue di nuovo il blocco o arresta il ciclo a seconda del risultato.Again it calls MoveNext and Current to return the next element, and again it either runs the block or stops the loop depending on the result. Questo processo continua fino a quando non MoveNext indica che non è presente alcun elemento successivo o viene rilevata un'istruzione Exit For.This process continues until MoveNext indicates that there is no next element or an Exit For statement is encountered.

Modifica della raccolta.Modifying the Collection. L'oggetto enumeratore restituito da GetEnumerator in genere non consente di modificare la raccolta aggiungendo, eliminando, sostituendo o riordinando gli elementi.The enumerator object returned by GetEnumerator normally doesn't let you change the collection by adding, deleting, replacing, or reordering any elements. Se si modifica la raccolta dopo che è stato avviato un ciclo For Each...Next, l'oggetto enumeratore diventa non valido e il tentativo successivo di accedere a un elemento causa un'eccezione InvalidOperationException.If you change the collection after you have initiated a For Each...Next loop, the enumerator object becomes invalid, and the next attempt to access an element causes an InvalidOperationException exception.

Tuttavia, questo blocco di modifiche non è determinato dall'Visual Basic, bensì dall'implementazione dell'interfaccia IEnumerable.However, this blocking of modification isn't determined by Visual Basic, but rather by the implementation of the IEnumerable interface. È possibile implementare IEnumerable in modo da consentire la modifica durante l'iterazione.It is possible to implement IEnumerable in a way that allows for modification during iteration. Se si sta valutando questa modifica dinamica, assicurarsi di comprendere le caratteristiche dell'implementazione di IEnumerable nella raccolta in uso.If you are considering doing such dynamic modification, make sure that you understand the characteristics of the IEnumerable implementation on the collection you are using.

Modifica degli elementi della raccolta.Modifying Collection Elements. La proprietà Current dell'oggetto enumeratore è ReadOnlye restituisce una copia locale di ogni elemento della raccolta.The Current property of the enumerator object is ReadOnly, and it returns a local copy of each collection element. Ciò significa che non è possibile modificare gli elementi stessi in un ciclo For Each...Next.This means that you cannot modify the elements themselves in a For Each...Next loop. Eventuali modifiche apportate influiscono solo sulla copia locale da Current e non vengono riflesse nella raccolta sottostante.Any modification you make affects only the local copy from Current and isn't reflected back into the underlying collection. Tuttavia, se un elemento è un tipo riferimento, è possibile modificare i membri dell'istanza a cui fa riferimento.However, if an element is a reference type, you can modify the members of the instance to which it points. Nell'esempio seguente viene modificato il membro BackColor di ogni elemento di thisControl.The following example modifies the BackColor member of each thisControl element. Tuttavia, non è possibile modificare thisControl.You cannot, however, modify thisControl itself.

Sub LightBlueBackground(thisForm As System.Windows.Forms.Form)
    For Each thisControl In thisForm.Controls
        thisControl.BackColor = System.Drawing.Color.LightBlue
    Next thisControl
End Sub

Nell'esempio precedente è possibile modificare il membro BackColor di ogni elemento thisControl, anche se non è possibile modificare thisControl stesso.The previous example can modify the BackColor member of each thisControl element, although it cannot modify thisControl itself.

Attraversamento di matrici.Traversing Arrays. Poiché la classe Array implementa l'interfaccia IEnumerable, tutte le matrici espongono il metodo GetEnumerator.Because the Array class implements the IEnumerable interface, all arrays expose the GetEnumerator method. Ciò significa che è possibile scorrere una matrice con un ciclo diNext For Each....This means that you can iterate through an array with a For Each...Next loop. Tuttavia, è possibile leggere solo gli elementi della matrice.However, you can only read the array elements. Non è possibile modificarli.You cannot change them.

EsempioExample

Nell'esempio seguente vengono elencate tutte le cartelle presenti in C:\ la directory tramite la classe DirectoryInfo.The following example lists all the folders in the C:\ directory by using the DirectoryInfo class.

Dim dInfo As New System.IO.DirectoryInfo("c:\")
For Each dir As System.IO.DirectoryInfo In dInfo.GetDirectories()
    Debug.WriteLine(dir.Name)
Next

EsempioExample

L'esempio seguente illustra una procedura per ordinare una raccolta.The following example illustrates a procedure for sorting a collection. Nell'esempio vengono ordinate le istanze di una classe Car archiviate in un List<T>.The example sorts instances of a Car class that are stored in a List<T>. La classe Car implementa l'interfaccia IComparable<T>, che richiede l'implementazione del metodo CompareTo.The Car class implements the IComparable<T> interface, which requires that the CompareTo method be implemented.

Ogni chiamata al metodo CompareTo esegue un confronto singolo usato per l'ordinamento.Each call to the CompareTo method makes a single comparison that's used for sorting. Il codice scritto dall'utente presente nel metodo CompareTo restituisce un valore per ogni confronto dell'oggetto corrente con un altro oggetto.User-written code in the CompareTo method returns a value for each comparison of the current object with another object. Il valore restituito è minore di zero se l'oggetto corrente è inferiore all'altro oggetto, maggiore di zero se l'oggetto corrente è superiore all'altro oggetto e zero se sono uguali.The value returned is less than zero if the current object is less than the other object, greater than zero if the current object is greater than the other object, and zero if they are equal. In questo modo è possibile definire nel codice i criteri di maggiore, minore e uguale.This enables you to define in code the criteria for greater than, less than, and equal.

Nel metodo ListCars l'istruzione cars.Sort() ordina l'elenco.In the ListCars method, the cars.Sort() statement sorts the list. Questa chiamata al metodo Sort di List<T> determina la chiamata automatica al metodo CompareTo per gli oggetti Car in List.This call to the Sort method of the List<T> causes the CompareTo method to be called automatically for the Car objects in the List.

Public Sub ListCars()

    ' Create some new cars.
    Dim cars As New List(Of Car) From
    {
        New Car With {.Name = "car1", .Color = "blue", .Speed = 20},
        New Car With {.Name = "car2", .Color = "red", .Speed = 50},
        New Car With {.Name = "car3", .Color = "green", .Speed = 10},
        New Car With {.Name = "car4", .Color = "blue", .Speed = 50},
        New Car With {.Name = "car5", .Color = "blue", .Speed = 30},
        New Car With {.Name = "car6", .Color = "red", .Speed = 60},
        New Car With {.Name = "car7", .Color = "green", .Speed = 50}
    }

    ' Sort the cars by color alphabetically, and then by speed
    ' in descending order.
    cars.Sort()

    ' View all of the cars.
    For Each thisCar As Car In cars
        Debug.Write(thisCar.Color.PadRight(5) & " ")
        Debug.Write(thisCar.Speed.ToString & " ")
        Debug.Write(thisCar.Name)
        Debug.WriteLine("")
    Next

    ' Output:
    '  blue  50 car4
    '  blue  30 car5
    '  blue  20 car1
    '  green 50 car7
    '  green 10 car3
    '  red   60 car6
    '  red   50 car2
End Sub

Public Class Car
    Implements IComparable(Of Car)

    Public Property Name As String
    Public Property Speed As Integer
    Public Property Color As String

    Public Function CompareTo(ByVal other As Car) As Integer _
        Implements System.IComparable(Of Car).CompareTo
        ' A call to this method makes a single comparison that is
        ' used for sorting.

        ' Determine the relative order of the objects being compared.
        ' Sort by color alphabetically, and then by speed in
        ' descending order.

        ' Compare the colors.
        Dim compare As Integer
        compare = String.Compare(Me.Color, other.Color, True)

        ' If the colors are the same, compare the speeds.
        If compare = 0 Then
            compare = Me.Speed.CompareTo(other.Speed)

            ' Use descending order for speed.
            compare = -compare
        End If

        Return compare
    End Function
End Class

Vedere ancheSee also