Visual Basic 2012 Voorbeelden
   

visual basic 2012 broncode voorbeelden

Blijf op de hoogte van de recente aanpassingen op vbvoorbeelden!

Microsoft Visual Studio 2012Microsoft Developers Network - Visual BasicMicrosoft .NET Framework

26.2. Query Methods

Print Email Deel op Twitter Deel op Facebook

Dit artikel is gepubliceerd op maandag 15 oktober 2012 op vbvoorbeelden, bezoek de website voor een recente versie van dit artikel of andere artikels.

26.2.1. Eigen Query Method

Om eenvoudig op al onze IEnumerable(Of T) collecties op basis van een conditie bepaalde elementen te selecteren, zouden we aan IEnumerable(Of T) een method kunnen toevoegen (via extension methods), die op basis van een predicate elementen gaat selecteren.

Deze extension method (hier GetWhere) is hier gedefinieerd in de module MyEnumerable.
Visual Basic 2012 Broncode - Codevoorbeeld 665
Option Strict On
Option Infer On
Public Class Counter
    Public Property Value As Integer
End Class
Public Module MyEnumerable
    <System.Runtime.CompilerServices.Extension()> _
    Public Function GetWhere(Of T)(ByVal source As IEnumerable(Of T), _
                                   ByVal predicate As Func(Of T, Boolean)) _
                                                            As IEnumerable(Of T)
        Dim getWhereList As New List(Of T)
        For Each item As T In source
            If Predicate.Invoke(item) Then
                getWhereList.Add(item)
            End If
        Next
        GetWhere = getWhereList
    End Function
End Module
Public Class Example1
    Public Shared Sub Main()
        Dim source = New Counter() {New Counter With {.Value = 10}, _
                                    New Counter With {.Value = 20}, _
                                    New Counter With {.Value = 30}}
        Dim predicate As Func(Of Counter, Boolean) = _
                                            Function(counter) counter.Value > 15
        Dim query1 = MyEnumerable.GetWhere(source, predicate)              ' (1)
        For Each counter As Counter In query1
            Console.WriteLine(counter.Value)
        Next
        Console.WriteLine()
        '
        Dim query2 = source.GetWhere(Function(counter) counter.Value < 25) ' (2)
        For Each counter As Counter In query2
            Console.WriteLine(counter.Value)
        Next
        '
        Console.ReadLine()
    End Sub
End Class
Console Application Output
20
30

10
20
We kunnen rechtstreeks deze extension method aanroepen (1) of aanroepen op eender welke instantie van het type IEnumerable(Of T) (2).

Bemerk hoe we bij een call naar onze extension method het actueel generisch parametertype niet hoeven te specifiëren, deze kan immers worden afgeleid van T van IEnumerable(Of T).
Variabele source bijvoorbeeld is een Counter() of dus ook een IEnumerable(Of Counter), gezien de extension method GetWhere(Of T) aangeeft een uitbreiding te zijn op IEnumerable(Of T) hoeven we deze dus niet te specifiëren bij de call.
Je mag dit echter wel doen, de call source.GetWhere(Function(counter) counter.Value < 25) kan je evengoed formuleren als source.GetWhere(Of Counter)(Function(counter) counter.Value < 25).

Voor meer details over extension methods, zie het desbetreffende topic.

26.2.2. Where

Het uitbreiden van IEnumerable(Of T) met dergelijke extension method is eigenlijk niet meer noodzakelijk.
De klasse System.Linq.Enumerable definieert reeds een extension method Where(Of TSource)(ByVal source As IEnumerable(Of TSource), ByVal predicate As Func(Of TSource, Boolean)) As IEnumerable(Of TSource) die in scope is indien namespace System.Linq geïmporteerd wordt.
Visual Basic 2012 Broncode - Codevoorbeeld 666
Public Class Example2
    Public Shared Sub Main()
        Dim source = New Counter() {New Counter With {.Value = 10}, _
                                    New Counter With {.Value = 20}, _
                                    New Counter With {.Value = 30}}
        Dim predicate As Func(Of Counter, Boolean) = _
                                            Function(counter) counter.Value > 15
        Dim query1 = System.Linq.Enumerable.Where(source, predicate)
        For Each counter As Counter In query1
            Console.WriteLine(counter.Value)
        Next
        Console.WriteLine()
        '
        Dim query2 = source.Where(Function(counter) counter.Value < 25)
        For Each counter As Counter In query2
            Console.WriteLine(counter.Value)
        Next
        '
        Console.ReadLine()
    End Sub
End Class
Console Application Output
20
30

10
20
Men kan ervoor opteren toch zelf (extension) methods te definiëren (met identieke identifier en signatuur) om zo van het in System.Linq.Enumerable gedefinieerde gedrag af te zien.  Gewone instance methods, of "dichterbij" gedefinieerde extension methods zullen immers voorrang krijgen.
Hadden we bijvoorbeeld de extension method GetWhere uit klasse MyEnumerable de identifier Where gegeven, dan werd deze aangeroepen in de expressie source.Where(...).

Deze in Enumerable gedefinieerde Where wordt ook wel een "query method" genoemd, omdat deze bruikbaar is om data te gaan raadplegen/filteren/querieën.

26.2.3. OfType

Een andere uiterst nuttige query extension method uit de Enumerable klasse is OfType(Of TResult)(ByVal source As IEnumerable) As IEnumerable(Of TResult).

Deze extensie van IEnumerable staat ons toe alle IEnumerable collecties te filteren naar strongly typed IEnumerable(Of T) collecties.
Visual Basic 2012 Broncode - Codevoorbeeld 667
Public Class Example3
    Public Shared Sub Main()
        Dim source1 = New Object() {1, "two", "3"c, "four", 5.0}
        Dim words As IEnumerable(Of String) = source1.OfType(Of String)()
        For Each word As String In words
            Console.WriteLine(word)
        Next
        Console.WriteLine()
        '
        Dim source2 As New ArrayList
        source2.Add(New Counter With {.Value = 10})
        source2.Add(New Counter With {.Value = 20})
        source2.Add(New Counter With {.Value = 30})
        Dim counters As IEnumerable(Of Counter) = source2.OfType(Of Counter)()
        For Each counter As Counter In counters
            Console.WriteLine(counter.Value)
        Next
        '
        Console.ReadLine()
    End Sub
End Class
Console Application Output
two
four

10
20
30
Uit de IEnumerable collectie source1 (met elementen van type Object) worden hier de elementen gehaald van het type String en in een strongly typed IEnumerable(Of String) collectie geplaatst.

Bemerk hoe querymethods als Where en OfType zowel werken op een IEnumerable(Of T) instantie als een IEnumerable(Of T) opleveren.

Dat maakt dat de opgestelde queries oneindig complex kunnen zijn.
Visual Basic 2012 Broncode - Codevoorbeeld 668
Public Class Example4
    Public Shared Sub Main()
        Dim source = New Object() {1, "two", "3"c, "four", 5.0}
        Dim predicate1 As Func(Of String, Boolean) = _
                                               Function(text) text.Contains("o")
        Dim predicate2 As Func(Of String, Boolean) = _
                                             Function(text) text.StartsWith("f")
        Dim words As IEnumerable(Of String)
        words = source.OfType(Of String).Where(predicate1).Where(predicate2)
        For Each word As String In words
            Console.WriteLine(word)
        Next
        '
        Console.ReadLine()
    End Sub
End Class
Console Application Output
four

26.2.4. Deferred Query Evaluation

Zoals je in onderstaand voorbeeld kan zien, zal de inhoud van een query, hier opgesteld via de Where method, slechts geëvalueerd worden op het moment dat deze query wordt gebruikt.

Bij definitie van de query wordt deze nog niet bepaald.

Als tussen de twee iteraties over de query (1) en (2) de source gemanipuleerd wordt, reflecteert deze wijziging zich ook in de tweede iteratie (2).

Je kan dit vergelijken met een For Each die itereert over de elementen van een collectie.  Een For Each zou gebruik moeten maken van de huidige toestand van de collectie waarover het itereert, wat verwezenlijkt kan worden aan de hand van het iterator pattern (of een yield statement in C#).  Als tussen twee For Eachs de collectie wordt gemanipuleerd, reflecteert dat in de tweede For Each.
Visual Basic 2012 Broncode - Codevoorbeeld 669
Public Class Example5
    Public Shared Sub Main()
        Dim source = New Counter() {New Counter With {.Value = 10}, _
                                    New Counter With {.Value = 20}, _
                                    New Counter With {.Value = 30}}
        Dim query = source.Where(Function(counter) True)
        '
        For Each counter As Counter In query                               ' (1)
            Console.WriteLine(counter.Value)
        Next
        Console.WriteLine()
        '
        source(1) = New Counter With {.Value = 200}
        '
        For Each counter As Counter In query                               ' (2)
            Console.WriteLine(counter.Value)
        Next
        '
        Console.ReadLine()
    End Sub
End Class
Console Application Output
10
20
30

10
200
30
Onze eigen GetWhere uit MyEnumerable vertoonde dat gedrag niet :
Visual Basic 2012 Broncode - Codevoorbeeld 670
Public Class Example6
    Public Shared Sub Main()
        Dim source = New Counter() {New Counter With {.Value = 10}, _
                                    New Counter With {.Value = 20}, _
                                    New Counter With {.Value = 30}}
        Dim query = source.GetWhere(Function(counter) True)
        '
        For Each counter As Counter In query                               ' (1)
            Console.WriteLine(counter.Value)
        Next
        Console.WriteLine()
        '
        source(1) = New Counter With {.Value = 200}
        '
        For Each counter As Counter In query                               ' (2)
            Console.WriteLine(counter.Value)
        Next
        '
        Console.ReadLine()
    End Sub
End Class
Console Application Output
10
20
30

10
20
30
De query werkt hier in beide iteraties ((1) en (2)) op dezelfde snapshot van de collectie.  Het resultaat van de query werd hier ook niet "deferred" maar meteen bij aanroep naar de GetWhere method bepaald.

Door in onze eigen query method een "iterator" op te leveren (die onthoudt welke de source is waarop hij werkt), zal pas bij iteratie over dit queryresultaat de nodige elementen worden gefilterd.
Visual Basic 2012 Broncode - Codevoorbeeld 671
Public Class WhereIterator(Of T) : Implements IEnumerable(Of T)
    Private _Source As IEnumerable(Of T)
    Private _Predicate As Func(Of T, Boolean)
    Public Sub New(ByVal source As IEnumerable(Of T), _
                   ByVal predicate As Func(Of T, Boolean))
        _Source = source
        _Predicate = predicate
    End Sub
    Public Function GetEnumerator() As IEnumerator(Of T) _
                                      Implements IEnumerable(Of T).GetEnumerator
        Dim list As New List(Of T)
        For Each sourceElement As T In _Source
            If _Predicate.Invoke(sourceElement) Then
                list.Add(sourceElement)
            End If
        Next
        GetEnumerator = list.GetEnumerator()
    End Function
    Protected Function GetWhereEnumerator() As IEnumerator _
                                            Implements IEnumerable.GetEnumerator
        GetWhereEnumerator = GetEnumerator()
    End Function
End Class
Public Module MySecondEnumerable
    <System.Runtime.CompilerServices.Extension()> _
    Public Function GetSecondWhere(Of T)( _
                                       ByVal source As IEnumerable(Of T), _
                                       ByVal predicate As Func(Of T, Boolean)) _
                                                            As IEnumerable(Of T)
        GetSecondWhere = New WhereIterator(Of T)(source, predicate)
    End Function
End Module
Public Class Example7
    Public Shared Sub Main()
        Dim source = New Counter() {New Counter With {.Value = 10}, _
                                    New Counter With {.Value = 20}, _
                                    New Counter With {.Value = 30}}
        Dim query = source.GetSecondWhere(Function(counter) True)
        '
        For Each counter As Counter In query                               ' (1)
            Console.WriteLine(counter.Value)
        Next
        Console.WriteLine()
        '
        source(1) = New Counter With {.Value = 200}
        '
        For Each counter As Counter In query                               ' (2)
            Console.WriteLine(counter.Value)
        Next
        '
        Console.ReadLine()
    End Sub
End Class
Console Application Output
10
20
30

10
200
30
De tweede iteratie over het queryresultaat reflecteert nu wel de wijzigingen in de sourcecollectie.

26.2.5. ToList en ToArray

De System.Linq.Enumerable klasse definieert een aantal extension methods die IEnumerable(Of T) uitbreiden met de mogelijkheid een query meteen te laten uitvoeren.
Visual Basic 2012 Broncode - Codevoorbeeld 672
Public Class Example8
    Public Shared Sub Main()
        Dim source = New Counter() {New Counter With {.Value = 10}, _
                                    New Counter With {.Value = 20}, _
                                    New Counter With {.Value = 30}}
        Dim query = source.Where(Function(counter) True)
        '
        Dim queryArray As Counter() = query.ToArray()
        Dim queryList As List(Of Counter) = query.ToList()
        '
        source(1) = New Counter With {.Value = 200}
        '
        For Each counter As Counter In queryArray                          ' (1)
            Console.WriteLine(counter.Value)
        Next
        Console.WriteLine()
        '
        For Each counter As Counter In queryList                           ' (2)
            Console.WriteLine(counter.Value)
        Next
        '
        Console.ReadLine()
    End Sub
End Class
Console Application Output
10
20
30

10
20
30
De queryArray en queryList worden hier meteen bij declaratie op hun eigen gequeryde resultaat geïnitialiseerd.

26.2.6. Singleton Queries

Andere query extensions van IEnumerable(Of T) die een singletonwaarde opleveren worden ook meteen geëvalueerd.
Visual Basic 2012 Broncode - Codevoorbeeld 673
Public Class Example9
    Public Shared Sub Main()
        Dim source = New Counter() {New Counter With {.Value = 10}, _
                                    New Counter With {.Value = 20}, _
                                    New Counter With {.Value = 30}}
        '
        Console.WriteLine(source.Any())
        Console.WriteLine(source.All(Function(counter) counter.Value Mod 2 = 0))
        Console.WriteLine(source.Average(Function(counter) counter.Value))
        Console.WriteLine(source.ElementAt(2).Value)
        Console.WriteLine(source.First().Value)
        '
        Console.ReadLine()
    End Sub
End Class
Console Application Output
True
True
20
30
10
Method Any levert True of False op naargelang de query resultaten bevat.

Method All levert True of False op naargelang alle items voldoen aan een bepaald predicaat.  Hier True omdat alle Counters een even Value hebben.

Method Average levert het gemiddelde op van de Decimal waarden van de items.  Average verwacht een selector die aangeeft hoe een item kan worden omgezet naar een Decimal.

Method ElementAt levert een item op een bepaalde positie (index) op.

Method First levert het eerste item op.

26.2.7. Projection met Select

De extension method Select(Of TSource, TResult)(ByVal source As IEnumerable(Of TSource), ByVal selector As Func(Of TSource, TResult)) As IEnumerable(Of TResult) kan gebruikt worden om de resultaten van een query (van TSource elementen) te projecten in een bepaald type ( TResult).

De selector specificeert de expressie die voorstelt hoe de resultaatwaarde wordt geprojecteerd.  Dit kan in de vorm van een anoniem type zijn (1).
Visual Basic 2012 Broncode - Codevoorbeeld 674
Public Class Person
    Public Property Name As String
    Public Property City As String
    Public Property IsMale As Boolean
End Class
Public Class Example10
    Public Shared Sub Main()
        Dim source = New Counter() {New Counter With {.Value = 10}, _
                                    New Counter With {.Value = 20}, _
                                    New Counter With {.Value = 30}}
        Dim selector1 As Func(Of Counter, Integer) = _
                                                 Function(counter) counter.Value
        Dim query1 = source.Select(selector1)
        For Each item As Integer In query1
            Console.WriteLine("Integer : " & item)
        Next
        Console.WriteLine()
        '
        Dim selector2 As Func(Of Counter, Counter) = Function(counter) counter
        Dim query2 = source.Select(selector2)
        For Each item As Counter In query2
            Console.WriteLine("Counter instance with Value : " & item.Value)
        Next
        Console.WriteLine()
        '
        Dim query3 = source.Where(Function(counter) counter.Value > 15) _
                           .Select(Function(counter) counter)
        For Each item As Counter In query3
            Console.WriteLine("Counter instance with Value : " & item.Value)
        Next
        Console.WriteLine()
        '
        Dim persons = New Person() { _
          New Person With {.Name = "John", .City = "New York", .IsMale = True}, _
          New Person With {.Name = "Jane", .City = "London", .IsMale = False}, _
          New Person With {.Name = "Paul", .City = "Paris", .IsMale = True}}
        Dim query4 = persons.Select(Function(person) _
                                    New With {person.Name, person.IsMale}) ' (1)
        For Each item In query4                                            ' (2)
            Console.WriteLine("Anonymous type instance with Name : " & _
                              item.Name & _
                              ", and IsMale : " & item.IsMale)
        Next
        Console.WriteLine()
        '
        Console.ReadLine()
    End Sub
End Class
Console Application Output
Integer : 10
Integer : 20
Integer : 30

Counter instance with Value : 10
Counter instance with Value : 20
Counter instance with Value : 30

Counter instance with Value : 20
Counter instance with Value : 30

Anonymous type instance with Name : John, and IsMale : True
Anonymous type instance with Name : Jane, and IsMale : False
Anonymous type instance with Name : Paul, and IsMale : True
Door het bestaan van deze anonieme types kunnen we in een resultaat-itemobject eender welke informatie uit het bronobject projecten.

Het datatype van item op regel (2) kan hier niet worden gespecificeerd, de items zijn van een anoniem type, waardoor het type van item inferred moet worden.

De With clausule bruikbaar in objectinitializer expressies is hier uitermate handig.  De lambda function heeft als body immers steeds één expressie die de returnwaarde voorstelt.  Als de lambda functie (als bijvoorbeeld een "selector") een nieuw object wil opleveren, dan kan deze dit nieuw object enkel instantiëren en properties initialiseren, in één expressie, indien deze gebruik maakt van een With clausule in de objectinitializer.

Bemerkt hoe de formeel generische parameter TSource inferred wordt op basis van het TSource van de IEnumerable(Of TSource) instantie waarop Select wordt aangeroepen.  Men hoeft hier dus geen actueel generische parameter voor TSource te specificeren.  Ook voor TResult is dit doorgaans niet noodzakelijk, deze kan worden gebaseerd op TResult van de selector.

26.2.8. OrderBy en OrderByDescending

Om de elementen van een IEnumerable(Of T) collectie in een bepaalde volgorde op te vragen kan men gebruik maken van de extension method OrderBy(Of TSource, TKey)(ByVal source As IEnumerable(Of TSource), ByVal keySelector As Func(Of TSource, TKey), ByVal comparer As IComparer(Of TKey)) As IOrderedEnumerable(Of TSource) en de gelijkaardige OrderByDescending.
Er is ook steeds een overladen versie voorzien zonder IComparer(Of T) argument.

Het spreekt voor zich dat men enkel op "comparable" key types kan sorteren.
Visual Basic 2012 Broncode - Codevoorbeeld 675
Partial Class Counter : Implements IComparable(Of Counter)
    Public Function CompareTo(ByVal other As Counter) As Integer _
                                   Implements IComparable(Of Counter).CompareTo
        CompareTo = Me.Value.CompareTo(other.Value)
    End Function
End Class
Public Class CounterAddition
    Public Property Operand1 As Counter
    Public Property Operand2 As Counter
    Public Function GetSum() As Counter
        GetSum = New Counter With {.Value = Operand1.Value + Operand2.Value}
    End Function
    Public Overrides Function ToString() As String
        ToString = Operand1.Value.ToString() & _
                   " + " & Operand2.Value.ToString() & _
                   " = " & GetSum().Value.ToString()
    End Function
End Class
Public Class FunkyCounterComparer : Implements IComparer(Of Counter)
    Public Function Compare(ByVal x As Counter, ByVal y As Counter) As Integer _
                                        Implements IComparer(Of Counter).Compare
        Compare = y.Value - x.Value
    End Function
End Class
Public Class Example11
    Public Shared Sub Main()
        Dim counter1 = New Counter With {.Value = 3}
        Dim counter2 = New Counter With {.Value = 4}
        Dim counter3 = New Counter With {.Value = 1}
        Dim counter4 = New Counter With {.Value = 3}
        Dim counter5 = New Counter With {.Value = 2}
        Dim counter6 = New Counter With {.Value = 5}
        Dim source1 = New CounterAddition() { _
         New CounterAddition With {.Operand1 = counter1, .Operand2 = counter2}, _
         New CounterAddition With {.Operand1 = counter3, .Operand2 = counter4}, _
         New CounterAddition With {.Operand1 = counter5, .Operand2 = counter6}}
        '
        Dim keySelector1 As Func(Of CounterAddition, Counter) = _
                                            Function(addition) addition.Operand1
        Dim query1 As IOrderedEnumerable(Of CounterAddition) = _
                                         source1.OrderByDescending(keySelector1)
        For Each item As CounterAddition In query1
            Console.WriteLine(item)
        Next
        Console.WriteLine()
        '
        Dim comparer1 As IComparer(Of Counter) = New FunkyCounterComparer
        Dim query2 = source1.OrderBy(keySelector1, comparer1)
        For Each item As CounterAddition In query2
            Console.WriteLine(item)
        Next
        '
        Console.ReadLine()
    End Sub
End Class
Console Application Output
3 + 4 = 7
2 + 5 = 7
1 + 3 = 4

3 + 4 = 7
2 + 5 = 7
1 + 3 = 4
Bemerk hoe deze methods IOrderedEnumerable(Of TSource) collecties opleveren.  Deze collecties zijn ook IEnumerable(Of TSource) collecties.

26.2.9. ThenBy en ThenByDescending

De ThenBy en ThenByDescending extension methods hebben een gelijkaardige signatuur als OrderBy en OrderByDescending.  Het verschil zit hem echter in het type dat deze methods extenden.  Then en ThenBy zijn extension methods voor het type IOrderedEnumerable(Of TSource).

Men gebruikt deze dus om ge-ordende queryresultaten verder te ordenen.
Visual Basic 2012 Broncode - Codevoorbeeld 676
Public Class Example12
    Public Shared Sub Main()
        Dim persons = New Person() { _
          New Person With {.Name = "Paul", .City = "New York", .IsMale = True}, _
          New Person With {.Name = "John", .City = "New York", .IsMale = True}, _
          New Person With {.Name = "John", .City = "London", .IsMale = False}}
        '
        Dim query1 = persons.OrderBy(Function(person) person.Name) _
                            .ThenBy(Function(person) person.City)
        For Each item As Person In query1
            Console.WriteLine(item.Name & " " & item.City)
        Next
        '
        Console.ReadLine()
    End Sub
End Class
Console Application Output
John London
John New York
Paul New York

26.2.10. Reverse

Method Reverse zal de elementen van de IEnumerable(Of TSource) collectie in omgekeerde volgorde opleveren.
Visual Basic 2012 Broncode - Codevoorbeeld 677
Public Class Example13
    Public Shared Sub Main()
        Dim persons = New Person() { _
          New Person With {.Name = "Paul", .City = "New York", .IsMale = True}, _
          New Person With {.Name = "John", .City = "New York", .IsMale = True}, _
          New Person With {.Name = "John", .City = "London", .IsMale = False}}
        '
        Dim query1 = persons.Reverse()
        For Each item As Person In query1
            Console.WriteLine(item.Name & " " & item.City)
        Next
        '
        Console.ReadLine()
    End Sub
End Class
Console Application Output
John London
John New York
Paul New York

26.2.11. GroupBy

De extension method GroupBy(Of TSource, TKey)(ByVal source As IEnumerable(Of TSource), ByVal keySelector As Func(Of TSource, TKey)) As IEnumerable(Of IGrouping(Of TKey, TSource)) zal de elementen van een sourcecollectie op basis van een key grouperen.
Het resultaat is een IEnumerable(Of IGrouping(Of TKey, TSource))
Visual Basic 2012 Broncode - Codevoorbeeld 678
Public Class Example14
    Public Shared Sub Main()
        Dim persons = New Person() { _
         New Person With {.Name = "John", .City = "New York", .IsMale = True}, _
         New Person With {.Name = "John", .City = "London", .IsMale = False}, _
         New Person With {.Name = "Paul", .City = "New York", .IsMale = True}}
        '
        Dim query1 As IEnumerable(Of IGrouping(Of String, Person)) = _
                                    persons.GroupBy(Function(person) person.City)
        For Each item As IGrouping(Of String, Person) In query1
            Console.WriteLine(item.Key)
            Dim itemEnumerator As IEnumerator(Of Person) = item.GetEnumerator()
            Do While itemEnumerator.MoveNext()
                Console.WriteLine("   - " & itemEnumerator.Current.Name)
            Loop
        Next
        Console.WriteLine()
        '
        Dim query2 = persons.GroupBy(Function(person) person.Name)
        For Each item In query2
            Console.WriteLine(item.Key)
            For Each itemElement In item
                Console.WriteLine("   - " & itemElement.City)
            Next
        Next
        '
        Console.ReadLine()
    End Sub
End Class
Console Application Output
New York
   - John
   - Paul
London
   - John

John
   - New York
   - London
Paul
   - New York
Er zijn ook overladen versies van GroupBy met argumenten voor een elementSelector, resultSelector en comparers.

26.2.12. Aggregate, Count, Min, Max en Average

Singleton query functies als Aggregate, Count, Min, Max en Average, leveren meteen een resultaat.

Methods Min, Max en Average werken op numerieke collecties, of verwachten een selector die een numerieke waarde selecteert.
Visual Basic 2012 Broncode - Codevoorbeeld 679
Public Class Example15
    Public Shared Sub Main()
        Dim words = New String() {"a", "bc", "def", "ghij", "klmno"}
        '
        Dim accumulator1 As Func(Of String, String, String) = _
                                            Function(text1, text2) text1 & text2
        Dim query1 As String = words.Aggregate(accumulator1)
        Console.WriteLine(query1)
        '
        Dim selector1 As Func(Of String, Integer) = Function(text) text.Length
        Console.WriteLine(words.Count())
        Console.WriteLine(words.Min(selector1))
        Console.WriteLine(words.Max(selector1))
        Console.WriteLine(words.Average(selector1))
        '
        Console.ReadLine()
    End Sub
End Class
Console Application Output
abcdefghijklmno
5
1
5
3

Dit artikel is gepubliceerd op maandag 15 oktober 2012 op vbvoorbeelden, bezoek de website voor een recente versie van dit artikel of andere artikels.