Servus!
Wie in diesem Thread hier: Bindingsource.Find bereits gefragt und weil ich LINQ auch in letzter Zeit immer mal wieder gebrauchen konnte, habe ich mir nun dazu entschlossen, ein kleines Tutorial über LINQ zu machen
Einführung:
Was ist LINQ überhaupt? LINQ steht für Language Integrated Query, auf deutsch: Sprachintegrierte Abfrage. Mit LINQ ist es möglich Sequenzen, d.h. Klassen, die das IEnumerable-Interface implementieren (=Basis-Interface für Enumerationsklassen, sprich Klassen, die eine Auflistung ermöglichen) zu "queryen". Das bedeutet im Endeffekt nichts anderes, als dass ich eine Liste, die ich bekomme, wie eine Datenbank abfragen kann, um mir gewisse Mengen (hier ist nicht der allgemein bekannte Ausdruck "Menge", sprich Quantität, gemeint, sondern der mathematische Terminus Menge - die Menge aller positiven, natürlichen Zahlen, kleiner 10 sind 0 bis 9 (eine mathematische Menge von Integern)) liefern zu lassen.
Bleiben wir bei dem bsp.
Will ich jetzt aus dieser Menge an Zahlen eine Untermenge haben (alle Zahlen mit Teilungsrest 0 bei Teilung durch 2), dann kann ich das entweder über eine For-Schleife und durchprobieren machen, oder ich löse das ganze mit LINQ - wer hätte es gedacht ;D
Eines Vorweg: LINQ ist NICHT dazu da, bereits bestehende Listen zu verändern (ist ja nur "Query" und nicht "Manipulate")! Heißt konkret: Wenn ich eine bestehende Liste mit LINQ filtere, erzeuge ich eine Kopie und arbeite von da an nur noch mit der Kopie, NICHT mit der originalen Liste. Änderungen der gefilterten Liste betreffen nicht die originale Liste!
Wie verwende ich LINQ?
Und da sind wir auch schon mitten drin! LINQ an sich hat den großen Vorteil: Man spart sich unglaublich viel Code (und Nerven) - falls man es richtig verwendet.
Um jetzt besagte Abfragen durchführen zu können braucht man eigentlich nur 2 Sachen: Das .NET Framework 3.5 und den Namespace System.Linq importieren
Für die Verwendung von LINQ gibt es zwei verschiedene Anlaufstellen: Entweder über die Erweiterungsmethoden aus System.Linq der Klasse Enumerable oder über sprachintegriere Keywords (FROM, WHERE,...). Beide Möglichkeiten lieferen als Ergebnis wieder ein IEnumerable-Sequenz.
Wie bei dem vorher benannten Beispiel kann ich jetzt aus der Menge von ganzen Zahlen (Integern) mir eine Untermenge ausgeben lassen:
Wer sich mal unter Visual Studio den Katalog an LINQ-Erweiterungsmethoden angesehen hat, wird feststellen, dass es insgesamt 44 verschiedene Erweiterungen gibt - diese jedoch in diversen Überladungen (20 alleine für Sum())
Ich gehe mal davon aus, dass man im normalen Alltag nicht recht viel mehr als eine Hand voll dieser Methoden braucht. Ich werde mich hier allerdings auch nur über die folgenden Methoden auslassen. Falls andere gefragt sind, bitte melden, ich werde das Tut ASAP editieren
Spoiler anzeigen
Any
Cast
Count
ElementAt
First
GroupBy
Last
OrderBy
Select
ToArray
ToList
Where
Any()
Wenn man sich die Signatur und den Rückgabewert von Any() ansieht, stellt man fest, dies Methode will keine Parameter und gibt einen Boolean zurück. Diese Methode ist von der Verwendung her dazu gedacht, zu prüfen, ob ein Sequenz überhaupt Elemente enthält. Geschwindigkeitstechnisch nehmen sich die beiden nicht wirklich viel (einfach mal nach "vb any vs count" googlen - oder dem Link folgen). Der Rückgabewert Boolean besagt wie gesagt nur, ob Elemente vorhanden sind oder nicht, Count kann gleichzeitig auch auswerten, wie viele Elemente es genau sind.
Dabei hat die Any()-Methode auch eine Überladung, welche es dem Programmierer erlaubt, ein Predicate, also eine Bedingung - anzugeben, nach welchem Unterschieden werden soll. So kann gesucht werden, ob die Liste Elemente enthält, welche sich Modulus 2 teilen lassen und als Restwert 0 ergeben.
Cast
Diese Methode erlaubt es jedes Element der originalen Sequenz in einen anderen Typen zu casten (Sequenz von Integern in eine von Shorts oder UIntegern)
Count
Die Count-Erweiterung erlaubt es die Elemente der Sequenz zu zählen, dabei kann wie bei fast jeder Überladung ein Predicate mitgegeben werden, anhand der die Ergebnise eingeschränkt werden(wie bei Any, nur Elemente mit Modulo 2 = 0)
ElementAt
Ist der Gegenpart zur Find()-Methode, hierfür muss nicht ein Attribut sondern der Index bekannt sein. Die ElementAt Methode fordert den Index und liefert eine Referenz auf das gewünschte Element
First
First() Liefert eine Referenz auf das erste Element der Sequenz, bestückt mir einem Predicate kann auch angegeben werden, welche Bedinung das erste Element erfüllen muss. So kann aus einer Liste von Mitarbeitern der erste mit Alter größer 35 bestimmt werden. Hierzu im Predicate einen "Mitarbeiter empfangen" und das Ergebnis des Vergleichs "Alter größer 35" zurück geben
Falls kein Element vorhanden ist, oder auf das Predicate zutrifft, wird eine
GroupBy
GroupBy erledigt das selbe wie die gleichnamige SQL-Anweisung und gruppiert die Elemente einer Sequenz. Da es für die Methode jedoch sehr viele, seeehr komplizierte Überladungen gibt, werde ich mir hier nur auf die erste beschränken:
Hierzu wird der Methode wieder ein Predicate mit gegeben, welches überprüfen soll, ob die Zahl Modulo 2 gleich 0 ergibt. Es wird eine Sequenz von IGrouping(Of Boolean, Integer) zurück gegeben. Diese Sequen enthält 2 Listen. Einmal die mit Restwert 0 und dann die mit Restwert != 2
Last
Funktioniert genau so wie First(), hat ebenfalls eine Überladung mit Predicate, liefert nur nicht das ERSTE sondern das Letzte Element der Sequenz
OrderBy
Liefert eine aufgesteigend sortierte Kopie der originalen Liste. Die Methode hat ebenfalls eine Erweiterung, dieser kann man einen IComparer übergeben, den man selber neu implementieren kann, um so auch eigene Datentypen sortieren zu können. Mit einer Integer-Auflistung lässt sich das schlecht machen, einfach mal MSDN nachschlagen
OrderBy hat als Rückgabewert ein IOrderedEnumerable, welches über ThenDescending() weiter sortiert werden kann.
SelectLaut MSDN: Projeziert jedes Elemente einer Sequenz in eine neue Form. Bedeutet: Man erhält eine bearbeitet Kopie der originalen Liste, ohne Ausschlüsse. So kann aus einer Liste von Teilnehmern oder Mitarbeitern ein Kürzelfeld mit den ersten 3 Buchstaben von Nach- und Vornamen gefüllt werden und das mit nur einer einzigen Zeile!
ToArray und ToList
Ich gehe mal davon aus, diese Methoden sind selbst erklärend.
Where
Last but not Least - Least wäre die Zip-Methode ;D - die Where-Methode. Diese Methode ist gedacht, um Wertemengen zu filtern und nur bestimmte Einträge zu übernehmen. Auf Ebene von List(Of ) gibt es dann die Find()-Methode, machen im Prinzip das selbe, Find ist aber wie gesagt erst ab List verfügbar.
Sprachintegrierte Schlüsselwörter
Wie im ersten Beispiel gegeben, ist neben den Erweiterungen der Enumerable-Klasse aus System.Linq auch die Abfrage über sprachintegrierte Schlüsselwörter möglich (Danke @thefiloe). Dabei können Queries, die wie SQL-Statements gelesen werden können direkt im Quellcode erzeugt werden. Mit allen Vorteilen, die Visual Studio mit sich bringt: AutoCompletion, IntelliSense, Typenprüfung, etc. Dabei ist es möglich SQL-Abfragen, die man vorher über beliebige DbCommand-Objekte auf der Datenbank ausgeführt hat, fast komplett übernehmen zu können. So wird aus einer SQL-Abfrage, die aus einer Datenbank mit mehreren Tabellen eine Menge an Daten zieht, durch einfache Sprachintegration eine übersichtliche, durch den Code-Editor (layout-technisch) unterstütze Linq-Abfrage.
Eine Beispielanwendung werde ich nachliefern, sobald ich bei mir die Datenbank zum laufen gebracht habe.
Abschluss:
Zum Ende: LINQ an sich ist echt eine super Erfindung, auch wenn es aufgrund des ganzen Generischen von der Dokumentation her schwer zu lesen ist, aber wenn man es mal raus hat, dann kann man recht gut damit arbeiten. Wenn sich wer von euch noch weiter mit dem Thema auseinander setzen will, kann ich nur empfehlen sich entweder auf MSDN die Artikel durchzulesen (einfach mal nach msdn und LINQ googlen, die ersten 3 Treffer) oder sich das Buch Datenbank-Programmierung mit Visual C# 2012 von Microsoft Press (gibts auch in VB.NET ;D) zuzulegen. Wie im Titel bereits verraten, es soll nur ein Einstieg sein - das Ganze in einem Tut zu verpacken ist IMHO unmöglich, dafür ist LINQ zu groß.
Danke für's lesen und viel Spaß
Lg Radinator
~blaze~: Thema verschoben
Wie in diesem Thread hier: Bindingsource.Find bereits gefragt und weil ich LINQ auch in letzter Zeit immer mal wieder gebrauchen konnte, habe ich mir nun dazu entschlossen, ein kleines Tutorial über LINQ zu machen
Einführung:
Was ist LINQ überhaupt? LINQ steht für Language Integrated Query, auf deutsch: Sprachintegrierte Abfrage. Mit LINQ ist es möglich Sequenzen, d.h. Klassen, die das IEnumerable-Interface implementieren (=Basis-Interface für Enumerationsklassen, sprich Klassen, die eine Auflistung ermöglichen) zu "queryen". Das bedeutet im Endeffekt nichts anderes, als dass ich eine Liste, die ich bekomme, wie eine Datenbank abfragen kann, um mir gewisse Mengen (hier ist nicht der allgemein bekannte Ausdruck "Menge", sprich Quantität, gemeint, sondern der mathematische Terminus Menge - die Menge aller positiven, natürlichen Zahlen, kleiner 10 sind 0 bis 9 (eine mathematische Menge von Integern)) liefern zu lassen.
Bleiben wir bei dem bsp.
Menge aller positiven, natürlichen Zahlen, kleiner 10
. Wenn ich diese Zahlenmenge erhalten will, dann werden diese von einem Anfänge der Programmierung gerne in einem banalen Array gespeichert:Will ich jetzt aus dieser Menge an Zahlen eine Untermenge haben (alle Zahlen mit Teilungsrest 0 bei Teilung durch 2), dann kann ich das entweder über eine For-Schleife und durchprobieren machen, oder ich löse das ganze mit LINQ - wer hätte es gedacht ;D
Eines Vorweg: LINQ ist NICHT dazu da, bereits bestehende Listen zu verändern (ist ja nur "Query" und nicht "Manipulate")! Heißt konkret: Wenn ich eine bestehende Liste mit LINQ filtere, erzeuge ich eine Kopie und arbeite von da an nur noch mit der Kopie, NICHT mit der originalen Liste. Änderungen der gefilterten Liste betreffen nicht die originale Liste!
Wie verwende ich LINQ?
Und da sind wir auch schon mitten drin! LINQ an sich hat den großen Vorteil: Man spart sich unglaublich viel Code (und Nerven) - falls man es richtig verwendet.
Um jetzt besagte Abfragen durchführen zu können braucht man eigentlich nur 2 Sachen: Das .NET Framework 3.5 und den Namespace System.Linq importieren
Für die Verwendung von LINQ gibt es zwei verschiedene Anlaufstellen: Entweder über die Erweiterungsmethoden aus System.Linq der Klasse Enumerable oder über sprachintegriere Keywords (FROM, WHERE,...). Beide Möglichkeiten lieferen als Ergebnis wieder ein IEnumerable-Sequenz.
Wie bei dem vorher benannten Beispiel kann ich jetzt aus der Menge von ganzen Zahlen (Integern) mir eine Untermenge ausgeben lassen:
VB.NET-Quellcode
- Imports System.Linq
- Module Module1
- Sub Main()
- 'Das besprochene Array
- Dim menge() As Integer = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
- 'Die erste Möglichkeite (kürzere Variante)
- Dim menge21 = menge.Where(Function(z) z Mod 2 = 0)
- 'Die zweite (wenn komplexere Bedinungen zutreffen müssen)
- Dim menge22 = menge.Where(Function(z)
- Return z Mod 2 = 0
- End Function)
- 'Die dritte Variante mit From und Where
- Dim menge3 = From m In menge
- Where m Mod 2 = 0
- End Sub
- End Module
Wer sich mal unter Visual Studio den Katalog an LINQ-Erweiterungsmethoden angesehen hat, wird feststellen, dass es insgesamt 44 verschiedene Erweiterungen gibt - diese jedoch in diversen Überladungen (20 alleine für Sum())
Ich gehe mal davon aus, dass man im normalen Alltag nicht recht viel mehr als eine Hand voll dieser Methoden braucht. Ich werde mich hier allerdings auch nur über die folgenden Methoden auslassen. Falls andere gefragt sind, bitte melden, ich werde das Tut ASAP editieren
Any
Cast
Count
ElementAt
First
GroupBy
Last
OrderBy
Select
ToArray
ToList
Where
Any()
Wenn man sich die Signatur und den Rückgabewert von Any() ansieht, stellt man fest, dies Methode will keine Parameter und gibt einen Boolean zurück. Diese Methode ist von der Verwendung her dazu gedacht, zu prüfen, ob ein Sequenz überhaupt Elemente enthält. Geschwindigkeitstechnisch nehmen sich die beiden nicht wirklich viel (einfach mal nach "vb any vs count" googlen - oder dem Link folgen). Der Rückgabewert Boolean besagt wie gesagt nur, ob Elemente vorhanden sind oder nicht, Count kann gleichzeitig auch auswerten, wie viele Elemente es genau sind.
Dabei hat die Any()-Methode auch eine Überladung, welche es dem Programmierer erlaubt, ein Predicate, also eine Bedingung - anzugeben, nach welchem Unterschieden werden soll. So kann gesucht werden, ob die Liste Elemente enthält, welche sich Modulus 2 teilen lassen und als Restwert 0 ergeben.
Cast
Diese Methode erlaubt es jedes Element der originalen Sequenz in einen anderen Typen zu casten (Sequenz von Integern in eine von Shorts oder UIntegern)
Count
Die Count-Erweiterung erlaubt es die Elemente der Sequenz zu zählen, dabei kann wie bei fast jeder Überladung ein Predicate mitgegeben werden, anhand der die Ergebnise eingeschränkt werden(wie bei Any, nur Elemente mit Modulo 2 = 0)
ElementAt
Ist der Gegenpart zur Find()-Methode, hierfür muss nicht ein Attribut sondern der Index bekannt sein. Die ElementAt Methode fordert den Index und liefert eine Referenz auf das gewünschte Element
First
First() Liefert eine Referenz auf das erste Element der Sequenz, bestückt mir einem Predicate kann auch angegeben werden, welche Bedinung das erste Element erfüllen muss. So kann aus einer Liste von Mitarbeitern der erste mit Alter größer 35 bestimmt werden. Hierzu im Predicate einen "Mitarbeiter empfangen" und das Ergebnis des Vergleichs "Alter größer 35" zurück geben
Falls kein Element vorhanden ist, oder auf das Predicate zutrifft, wird eine
InvalidOperationException
geworfen (Danke @Trade). Dies hat logischerweise zur Folge, dass das Programm abstürzt. Um besagte Exception zu vermeiden, kann man die FirstOrDefault-Erweiterung verwenden. Diese gibt im Falle eine Treffers das besagte erste Element zurück. Sollte sich jedoch kein Treffer finden, wird der Standardwert - in VB ist das Nothing
, in C# wäre es null
- zurück gegeben. Gleiches gilt auch für Last bzw. LastOrDefault!GroupBy
GroupBy erledigt das selbe wie die gleichnamige SQL-Anweisung und gruppiert die Elemente einer Sequenz. Da es für die Methode jedoch sehr viele, seeehr komplizierte Überladungen gibt, werde ich mir hier nur auf die erste beschränken:
Hierzu wird der Methode wieder ein Predicate mit gegeben, welches überprüfen soll, ob die Zahl Modulo 2 gleich 0 ergibt. Es wird eine Sequenz von IGrouping(Of Boolean, Integer) zurück gegeben. Diese Sequen enthält 2 Listen. Einmal die mit Restwert 0 und dann die mit Restwert != 2
Last
Funktioniert genau so wie First(), hat ebenfalls eine Überladung mit Predicate, liefert nur nicht das ERSTE sondern das Letzte Element der Sequenz
OrderBy
Liefert eine aufgesteigend sortierte Kopie der originalen Liste. Die Methode hat ebenfalls eine Erweiterung, dieser kann man einen IComparer übergeben, den man selber neu implementieren kann, um so auch eigene Datentypen sortieren zu können. Mit einer Integer-Auflistung lässt sich das schlecht machen, einfach mal MSDN nachschlagen
OrderBy hat als Rückgabewert ein IOrderedEnumerable, welches über ThenDescending() weiter sortiert werden kann.
SelectLaut MSDN: Projeziert jedes Elemente einer Sequenz in eine neue Form. Bedeutet: Man erhält eine bearbeitet Kopie der originalen Liste, ohne Ausschlüsse. So kann aus einer Liste von Teilnehmern oder Mitarbeitern ein Kürzelfeld mit den ersten 3 Buchstaben von Nach- und Vornamen gefüllt werden und das mit nur einer einzigen Zeile!
VB.NET-Quellcode
- Dim ma As New List(Of Mitarbeiter)
- ma = ma.Select(Function(m As Mitarbeiter)
- m.Kuerzel = m.Nachname.Substring(0, 3) & m.Vorname.Substring(0, 3)
- Return m
- End Function).ToList()
- 'Mitarbeiter:
- Public Class Mitarbeiter
- Public Property ID As Integer
- Public Property Nachname As String
- Public Property Vorname As String
- Public Property Kuerzel As String
- End Class
ToArray und ToList
Ich gehe mal davon aus, diese Methoden sind selbst erklärend.
Where
Last but not Least - Least wäre die Zip-Methode ;D - die Where-Methode. Diese Methode ist gedacht, um Wertemengen zu filtern und nur bestimmte Einträge zu übernehmen. Auf Ebene von List(Of ) gibt es dann die Find()-Methode, machen im Prinzip das selbe, Find ist aber wie gesagt erst ab List verfügbar.
Sprachintegrierte Schlüsselwörter
Wie im ersten Beispiel gegeben, ist neben den Erweiterungen der Enumerable-Klasse aus System.Linq auch die Abfrage über sprachintegrierte Schlüsselwörter möglich (Danke @thefiloe). Dabei können Queries, die wie SQL-Statements gelesen werden können direkt im Quellcode erzeugt werden. Mit allen Vorteilen, die Visual Studio mit sich bringt: AutoCompletion, IntelliSense, Typenprüfung, etc. Dabei ist es möglich SQL-Abfragen, die man vorher über beliebige DbCommand-Objekte auf der Datenbank ausgeführt hat, fast komplett übernehmen zu können. So wird aus einer SQL-Abfrage, die aus einer Datenbank mit mehreren Tabellen eine Menge an Daten zieht, durch einfache Sprachintegration eine übersichtliche, durch den Code-Editor (layout-technisch) unterstütze Linq-Abfrage.
Eine Beispielanwendung werde ich nachliefern, sobald ich bei mir die Datenbank zum laufen gebracht habe.
Abschluss:
Zum Ende: LINQ an sich ist echt eine super Erfindung, auch wenn es aufgrund des ganzen Generischen von der Dokumentation her schwer zu lesen ist, aber wenn man es mal raus hat, dann kann man recht gut damit arbeiten. Wenn sich wer von euch noch weiter mit dem Thema auseinander setzen will, kann ich nur empfehlen sich entweder auf MSDN die Artikel durchzulesen (einfach mal nach msdn und LINQ googlen, die ersten 3 Treffer) oder sich das Buch Datenbank-Programmierung mit Visual C# 2012 von Microsoft Press (gibts auch in VB.NET ;D) zuzulegen. Wie im Titel bereits verraten, es soll nur ein Einstieg sein - das Ganze in einem Tut zu verpacken ist IMHO unmöglich, dafür ist LINQ zu groß.
Danke für's lesen und viel Spaß
Lg Radinator
~blaze~: Thema verschoben
In general (across programming languages), a pointer is a number that represents a physical location in memory. A nullpointer is (almost always) one that points to 0, and is widely recognized as "not pointing to anything". Since systems have different amounts of supported memory, it doesn't always take the same number of bytes to hold that number, so we call a "native size integer" one that can hold a pointer on any particular system. - Sam Harwell
Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „~blaze~“ ()