| hoofdstuk |
32. 33. 34.  |
| onderwerp |
33.2. 33.3. Query Methods 33.4.  |
| rubrieken | 











|
Dit artikel is gepubliceerd op zondag 31 juli 2011 op vbvoorbeelden, bezoek de website voor een recente versie van dit artikel of andere artikels.
33.3.1. Eigen Query MethodOm 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 2010 Broncode Option Strict OnOption Infer OnPublic Class Counter Private m_Value As Integer Public Property Value() As Integer Get Value = m_Value End Get Set( ByVal value As Integer) m_Value = value End Set End PropertyEnd ClassPublic 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 FunctionEnd ModulePublic 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) For Each counter As Counter In query1 Console.WriteLine(counter.Value) Next Console.WriteLine() Dim query2 = source.GetWhere( Function(counter) counter.Value < 25) For Each counter As Counter In query2 Console.WriteLine(counter.Value) Next Console.ReadLine() End SubEnd ClassDownload Visual Basic 2010 Broncode Download Visual C# Sourcecode
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). 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. boven
33.3.2. WhereHet 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 2010 Broncode 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 SubEnd ClassDownload Visual Basic 2010 Broncode Download Visual C# Sourcecode
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. boven
33.3.3. OfTypeEen 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 2010 Broncode 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 SubEnd ClassDownload Visual Basic 2010 Broncode Download Visual C# Sourcecode
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 2010 Broncode 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 SubEnd ClassDownload Visual Basic 2010 Broncode Download Visual C# Sourcecode
Console Application Output four boven
33.3.4. Deferred Query EvaluationZoals 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 2010 Broncode 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 Console.WriteLine(counter.Value) Next Console.WriteLine() source(1) = New Counter With {.Value = 200} For Each counter As Counter In query Console.WriteLine(counter.Value) Next Console.ReadLine() End SubEnd ClassDownload Visual Basic 2010 Broncode Download Visual C# Sourcecode
Console Application Output 10
20
30
10
200
30 Onze eigen GetWhere uit MyEnumerable vertoonde dat gedrag niet : Visual Basic 2010 Broncode 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 Console.WriteLine(counter.Value) Next Console.WriteLine() source(1) = New Counter With {.Value = 200} For Each counter As Counter In query Console.WriteLine(counter.Value) Next Console.ReadLine() End SubEnd ClassDownload Visual Basic 2010 Broncode Download Visual C# Sourcecode
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 2010 Broncode Public Class WhereIterator( Of T) : Implements IEnumerable( Of T) Private m_Source As IEnumerable( Of T) Private m_Predicate As Func( Of T, Boolean) Public Sub New( ByVal source As IEnumerable( Of T), _ ByVal predicate As Func( Of T, Boolean)) m_Source = source m_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 m_Source If m_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 FunctionEnd ClassPublic 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 FunctionEnd ModulePublic 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 Console.WriteLine(counter.Value) Next Console.WriteLine() source(1) = New Counter With {.Value = 200} For Each counter As Counter In query Console.WriteLine(counter.Value) Next Console.ReadLine() End SubEnd ClassDownload Visual Basic 2010 Broncode Download Visual C# Sourcecode
Console Application Output 10
20
30
10
200
30 De tweede iteratie over het queryresultaat reflecteert nu wel de wijzigingen in de sourcecollectie. boven
33.3.5. ToList en ToArrayDe 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 2010 Broncode 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 Console.WriteLine(counter.Value) Next Console.WriteLine() For Each counter As Counter In queryList Console.WriteLine(counter.Value) Next Console.ReadLine() End SubEnd ClassDownload Visual Basic 2010 Broncode Download Visual C# Sourcecode
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. boven
33.3.6. Singleton QueriesAndere query extensions van IEnumerable(Of T) die een singletonwaarde opleveren worden ook meteen geëvalueerd. Visual Basic 2010 Broncode 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 SubEnd ClassDownload Visual Basic 2010 Broncode Download Visual C# Sourcecode
Console Application Output True
True
20
30
10 Any levert True of False op naargelang de query resultaten bevat.
All levert True of False op naargelang alle items voldoen aan een bepaald predicaat. Hier True omdat alle Counters een even Value hebben.
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.
ElementAt levert een item op een bepaalde positie ( index ) op.
First levert het eerste item op. boven
33.3.7. Projection met SelectDe 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 2010 Broncode Public Class Person Private m_Name As String Public Property Name() As String Get Return m_Name End Get Set( ByVal value As String) m_Name = value End Set End Property Private m_City As String Public Property City() As String Get Return m_City End Get Set( ByVal value As String) m_City = value End Set End Property Private m_IsMale As Boolean Public Property IsMale() As Boolean Get Return m_IsMale End Get Set( ByVal value As Boolean) m_IsMale = value End Set End PropertyEnd ClassPublic 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}) For Each item In query4 Console.WriteLine( "Anonymous type instance with Name : " & _ item.Name & _ ", and IsMale : " & item.IsMale) Next Console.WriteLine() Console.ReadLine() End SubEnd ClassDownload Visual Basic 2010 Broncode Download Visual C# Sourcecode
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. boven
33.3.8. OrderBy en OrderByDescendingOm 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 2010 Broncode 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 FunctionEnd ClassPublic Class CounterAddition Private m_Operand1 As Counter Public Property Operand1() As Counter Get Return m_Operand1 End Get Set( ByVal value As Counter) m_Operand1 = value End Set End Property Private m_Operand2 As Counter Public Property Operand2() As Counter Get Return m_Operand2 End Get Set( ByVal value As Counter) m_Operand2 = value End Set End Property 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 FunctionEnd ClassPublic 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 FunctionEnd ClassPublic 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 SubEnd ClassDownload Visual Basic 2010 Broncode Download Visual C# Sourcecode
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. boven
33.3.9. ThenBy en ThenByDescendingDe 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 2010 Broncode 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 SubEnd ClassDownload Visual Basic 2010 Broncode Download Visual C# Sourcecode
Console Application Output John London
John New York
Paul New York boven
33.3.10. ReverseReverse zal de elementen van de IEnumerable(Of TSource) collectie in omgekeerde volgorde opleveren. Visual Basic 2010 Broncode 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 SubEnd ClassDownload Visual Basic 2010 Broncode Download Visual C# Sourcecode
Console Application Output John London
John New York
Paul New York boven
33.3.11. GroupByDe 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 2010 Broncode 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 SubEnd ClassDownload Visual Basic 2010 Broncode Download Visual C# Sourcecode
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. boven
33.3.12. Aggregate, Count, Min, Max en AverageSingleton query functies als Aggregate, Count, Min, Max en Average, leveren meteen een resultaat.
Min, Max en Average werken op numerieke collecties, of verwachten een selector die een numerieke waarde selecteert. Visual Basic 2010 Broncode 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 SubEnd ClassDownload Visual Basic 2010 Broncode Download Visual C# Sourcecode
Console Application Output abcdefghijklmno
5
1
5
3
Dit artikel is gepubliceerd op zondag 31 juli 2011 op vbvoorbeelden, bezoek de website voor een recente versie van dit artikel of andere artikels.
|