Optimierungseinstellung im Reflector, oder: Wie sieht LINQ wirklich aus?
Beim dritten Treffen vom .NET Stammtisch Konstanz - Kreuzlingen habe ich einen Vortrag über LINQ gehalten.
Dabei wollte ich zeigen wie aus dem SQL ähnlichen Syntax von LINQ aneinandergereihte Methoden Aufrufe werden und aus den Lambda Ausdrücken jeweils anonyme Methoden.
Das geht über den Reflector auch wunderbar. Kurz vor dem Vortrag habe ich den Fehler begangen und Windows 7 installiert… nicht das Windows 7 der Fehler gewesen wäre, sondern die Neuinstallation.
So hatte ich vieles noch nicht 100% so wie es war und ausserdem war plötzlich die neuste Version vom Reflector installiert.
Als ich während dem Vortrag den Code demonstrieren wollte, bekamen wir natürlich nur wunderschöne Lambda-Ausdrücke zu sehen, keine anonymen Methoden. Ich wusste nicht wieso und hatte keine Zeit das herauszufinden.
Edit:
LINQ war das natürlich nicht, sondern nur Lambda-Ausdrücke.
Jedoch gilt das genau so für LINQ, dort wird die LINQ-Syntax automatisch vom Kompiler in den Erweiterungemethoden-Syntax + Lambda-Ausdrücke umgewandelt.
Natürlich kann auch von Hand der Erweiterungsmethoden-Syntax benutzt werden, bei einer Bedingung oder wirklich komplexen Aufgaben ist das meist angenehmer.
LINQ-Syntax
public Download GetDownloadByFileName(string fileName)
{
return (from download in this.GetList()
where download.FileName == fileName).SingleOrDefault();
}
Erweiterungsmethoden-Syntax
public Download GetDownloadByFileName(string fileName)
{
return this.GetList().Where(download => download.FileName == fileName);
}
.NET 3.5
public Download GetDownloadByFileName(string fileName)
{
return this.GetList(d => d.FileName == fileName).SingleOrDefault();
}
Eigentlich ist es relativ einfach, man gehe im Menü unter: View –> Options –> Disassembler und stellt bei Optimization .NET 2.0 ein, dann sieht es nämlich so aus:
public Download GetDownloadByFileName(string fileName)
{
return this.GetList(delegate (Download d) {
return d.FileName == fileName;
}).SingleOrDefault<Download>();
}
Wird None oder .NET 1.0 eingestellt ist der Code schon fast nicht mehr zu lesen.
Es ist hier gut zu erkennen, was der Kompiler im Hintergrund alles erzeugt damit die oben geschriebene Syntax funktioniert.
public Download GetDownloadByFileName(string fileName)
{
<>c__DisplayClass1 CS$<>8__locals2;
Download CS$1$0000;
CS$<>8__locals2 = new <>c__DisplayClass1();
CS$<>8__locals2.fileName = fileName;
CS$1$0000 = this.GetList(new Func<Download, bool>(CS$<>8__locals2.<GetDownloadByFileName>b__0)).SingleOrDefault<Download>();
Label_0028:
return CS$1$0000;
}
Bearbeitung / Korrekturen:
09.06.09 - Das Codesnippet zu .NET 2.0 war natürlich das falsche, jetzt sieht man auch die anonyme Methode.
09.09.09 - LINQ war ja nicht drin, ist jetzt hinzugefügt ;-)