Im 1. Quartal des neuen Jahres (2010) wird das Buch "SQL Server 2008 R2 - Das Entwicklerbuch" erscheinen. Für dieses Buch haben sich die Autoren darauf geeinigt, sollte es Programmierbeispiele geben, diese nach Möglichkeit auch in C# zur Verfügung zu stellen. Und so stolpere ich bei der Portierung von Beispielen von Visual Basic zu C# über LINQ to Objects, und ich muss feststellen - formulieren wir es im Kohlepott-Slang -, wie überlegen Visual Basic sein Compiler im Gegensatz zu C# seinem ist, wenn es um LINQ-Ausdrücke geht.
Ausgangspunkt war der zugegeben nicht ganz triviale LINQ-Ausdruck, der im Einführungskapitel die Mächtigkeit und Flexibilität von LINQ-Ausdrücken demonstrieren sollte. In Visual Basic sieht das folgendermaßen aus:
Dim adrListeGruppiert = From adrElement In adrListe _
Join artElement In artListe _
On adrElement.ID Equals artElement.IDGekauftVon _
Select adrElement.ID, adrElement.Nachname, _
adrElement.Vorname, adrElement.PLZ, _
artElement.ArtikelNummer, artElement.ArtikelName, _
artElement.Anzahl, artElement.Einzelpreis, _
Postenpreis = artElement.Anzahl * artElement.Einzelpreis _
Order By Nachname, ArtikelNummer _
Where (PLZ > "0" And PLZ < "50000") _
Group ArtikelNummer, ArtikelName, _
Anzahl, Einzelpreis, Postenpreis _
By ID, Nachname, Vorname _
Into Artikelliste = Group, AnzahlArtikel = Count(), _
Gesamtpreis = Sum(Postenpreis)
OK, und hier nun mein Angebot: Der erste, der es schafft, mir diesen Ausdruck nur mit sequentiellen LINQ-Anweisungen (keine geschachteteln From-Konstrukte, keine direkten Aufrufe von Extender-Methoden, keine Lambdas) in C# also genau nach dem Vorbild des obenstehenden Visual Basic-Ausdrucks zu schicken, bekommt ein Freiexemplar des ebenfalls oben erwähnten Buches!
Das beste Konstrukt, das ich vorweisen kann, ist folgendes (und es enthält natürlich Lambdas und direkte Extender-Methodenaufrufe):
var adrListeGruppiert = (from adrElement in adrListe
join artElement in artListe on adrElement.ID
equals artElement.IDGekauftVon
select new
{
adrElement.ID,
adrElement.Nachname,
adrElement.Vorname,
adrElement.PLZ,
artElement.ArtikelNummer,
artElement.ArtikelName,
artElement.Anzahl,
artElement.Einzelpreis,
Postenpreis = artElement.Anzahl * artElement.Einzelpreis
}).
OrderBy(o => o.Nachname).ThenBy(o1 => o1.ArtikelNummer).
Where(w => ((w.PLZ.CompareTo("0")==1) && (w.PLZ.CompareTo("50000")==-1))).
GroupBy(g => new { g.ID, g.Nachname, g.Vorname }).
Select(s => new
{
ID = s.Key.ID,
Nachname = s.Key.Nachname,
Vorname = s.Key.Vorname,
Artikelliste = s.ToArray(),
AnzahlArtikel = s.Count(),
Gesamtpreis = s.Sum(p => p.Postenpreis)
});