Warum kann ich beim Debuggen im Fenster "Schnellüberwachung" keine Lambda-Ausdrücke verwenden?
UPD: siehe auch
http://blogs.msdn.com/b/jaredpar/archive/2009/08/26/why-no-linq-in-debugger-windows.aspx
Warum kann ich beim Debuggen im Fenster "Schnellüberwachung" keine Lambda-Ausdrücke verwenden?
UPD: siehe auch
http://blogs.msdn.com/b/jaredpar/archive/2009/08/26/why-no-linq-in-debugger-windows.aspx
Antworten:
Lambda-Ausdrücke sind wie anonyme Methoden tatsächlich sehr komplexe Tiere. Selbst wenn wir dies ausschließen Expression
(.NET 3.5), bleibt dennoch eine Menge Komplexität, nicht zuletzt erfasste Variablen, die den Code, der sie verwendet, grundlegend neu strukturieren (was Sie als Variablen betrachten, werden zu Feldern in vom Compiler generierten Klassen). , mit ein bisschen Rauch und Spiegeln.
Daher bin ich nicht im geringsten überrascht, dass Sie sie nicht untätig verwenden können - es gibt eine Menge Compilerarbeit (und Typgenerierung hinter den Kulissen), die diese Magie unterstützt.
Nein, Sie können keine Lambda-Ausdrücke im Fenster watch / Locals / Instant verwenden. Wie Marc betont hat, ist dies unglaublich komplex. Ich wollte allerdings etwas weiter in das Thema eintauchen.
Was die meisten Leute bei der Ausführung einer anonymen Funktion im Debugger nicht berücksichtigen, ist, dass sie nicht in einem Vakuum auftritt. Das Definieren und Ausführen einer anonymen Funktion ändert die zugrunde liegende Struktur der Codebasis. Das Ändern des Codes im Allgemeinen und im Besonderen über das unmittelbare Fenster ist eine sehr schwierige Aufgabe.
Betrachten Sie den folgenden Code.
void Example() {
var v1 = 42;
var v2 = 56;
Func<int> func1 = () => v1;
System.Diagnostics.Debugger.Break();
var v3 = v1 + v2;
}
Dieser bestimmte Code erstellt einen einzelnen Abschluss, um den Wert v1 zu erfassen. Die Abschlusserfassung ist immer dann erforderlich, wenn eine anonyme Funktion eine Variable verwendet, die außerhalb ihres Gültigkeitsbereichs deklariert ist. In dieser Funktion existiert v1 in jeder Hinsicht nicht mehr. Die letzte Zeile sieht eigentlich eher wie folgt aus
var v3 = closure1.v1 + v2;
Wenn die Funktion Beispiel im Debugger ausgeführt wird, stoppt sie an der Break-Zeile. Stellen Sie sich nun vor, der Benutzer hätte Folgendes in das Überwachungsfenster eingegeben
(Func<int>)(() => v2);
Um dies ordnungsgemäß auszuführen, müsste der Debugger (oder besser der EE) einen Abschluss für die Variable v2 erstellen. Dies ist schwierig, aber nicht unmöglich.
Was dies für den EE wirklich schwierig macht, ist die letzte Zeile. Wie soll diese Zeile jetzt ausgeführt werden? In jeder Hinsicht hat die anonyme Funktion die Variable v2 gelöscht und durch Closure2.v2 ersetzt. Die letzte Codezeile muss also jetzt wirklich gelesen werden
var v3 = closure1.v1 + closure2.v2;
Um diesen Effekt tatsächlich im Code zu erzielen, muss der EE die letzte Codezeile ändern, bei der es sich tatsächlich um eine ENC-Aktion handelt. Dieses spezielle Beispiel ist zwar möglich, ein großer Teil der Szenarien jedoch nicht.
Was noch schlimmer ist, ist die Ausführung, dass der Lambda-Ausdruck keinen neuen Abschluss erzeugen sollte. Es sollten tatsächlich Daten an den ursprünglichen Abschluss angehängt werden. An dieser Stelle stoßen Sie direkt auf die Einschränkungen ENC.
Mein kleines Beispiel kratzt leider nur an der Oberfläche der Probleme, auf die wir stoßen. Ich sage immer wieder, ich schreibe einen vollständigen Blog-Beitrag zu diesem Thema und hoffe, dass ich dieses Wochenende Zeit habe.
Sie können keine Lambda-Ausdrücke in den Fenstern "Sofort" oder "Beobachten" verwenden.
Sie können jedoch System.Linq.Dynamic-Ausdrücke verwenden , die die Form .Where ("Id = @ 0", 2) haben. Sie verfügen nicht über alle in Standard-Linq verfügbaren Methoden und nicht über alle Methoden Kraft der Lambda-Ausdrücke, aber dennoch ist es besser als nichts!
.Any(string predicate)
, man kann : so etwas wie setzt .Where("Id>2").Any()
im Watch - Fenster, oder PIN -Nummer zu. Es ist toll!
Die Zukunft ist gekommen!
Die Unterstützung für das Debuggen von Lambda-Ausdrücken wurde zu Visual Studio 2015 hinzugefügt ( Vorschau zum Zeitpunkt des Schreibens).
Der Ausdrucksauswerter musste neu geschrieben werden, daher fehlen viele Funktionen: Remote-Debugging von ASP.NET, Deklarieren von Variablen im Sofortfenster, Überprüfen dynamischer Variablen usw. Auch Lambda-Ausdrücke, die Aufrufe nativer Funktionen erfordern, werden derzeit nicht unterstützt.
Dies könnte helfen: Erweitertes Sofortfenster für Visual Studio (verwenden Sie Linq, Lambda Expr beim Debuggen)
Alles Gute Patrick
Lambda-Ausdrücke werden vom Ausdrucksauswerter des Debuggers nicht unterstützt ... was nicht verwunderlich ist, da sie zur Kompilierungszeit eher zum Erstellen von Methoden (oder Ausdrucksbäumen) als von Ausdrücken verwendet werden (siehe Reflector mit auf .NET 2 umgeschalteter Anzeige) sieh sie dir an).
Außerdem könnten sie natürlich einen Verschluss bilden, eine weitere ganze Strukturschicht.
Expression
Bäume erstellen - das hängt vom Kontext ab.
In VS 2015 können Sie dies jetzt tun. Dies ist eine der neuen Funktionen, die sie hinzugefügt haben.
Wenn Sie Visual Studio 2013 weiterhin verwenden müssen, können Sie tatsächlich eine Schleife oder einen Lambda-Ausdruck in das unmittelbare Fenster schreiben, indem Sie auch das Paketmanager-Konsolenfenster verwenden. In meinem Fall habe ich oben in der Funktion eine Liste hinzugefügt:
private void RemoveRoleHierarchy()
{
#if DEBUG
var departments = _unitOfWork.DepartmentRepository.GetAll().ToList();
var roleHierarchies = _unitOfWork.RoleHierarchyRepository.GetAll().ToList();
#endif
try
{
//RoleHierarchy
foreach (SchoolBo.RoleHierarchy item in _listSoRoleHierarchy.Where(r => r.BusinessKeyMatched == false))
_unitOfWork.RoleHierarchyRepository.Remove(item.Id);
_unitOfWork.Save();
}
catch (Exception e)
{
Debug.WriteLine(e.ToString());
throw;
}
}
Wo meine GetAll()
Funktion ist:
private DbSet<T> _dbSet;
public virtual IList<T> GetAll()
{
List<T> list;
IQueryable<T> dbQuery = _dbSet;
list = dbQuery
.ToList<T>();
return list;
}
Hier wurde immer wieder der folgende Fehler angezeigt, daher wollte ich alle Elemente in den verschiedenen Repositorys ausdrucken:
InnerException {"Die DELETE-Anweisung stand in Konflikt mit der REFERENCE-Einschränkung" FK_dbo.Department_dbo.RoleHierarchy_OranizationalRoleId ". Der Konflikt trat in der Datenbank" CC_Portal_SchoolObjectModel ", Tabelle" dbo.Department "auf Anweisung wurde beendet. "} System.Exception {System.Data.SqlClient.SqlException}
Dann finde ich heraus, wie viele Datensätze sich im Abteilungsrepository befinden, indem ich dies im unmittelbaren Fenster ausführe:
_unitOfWork.DepartmentRepository.GetAll().ToList().Count
Welches 243 zurückgegeben.
Wenn Sie also Folgendes in der Paketmanagerkonsole ausführen, werden alle Elemente ausgedruckt:
PM> for($i = 0; $i -lt 243; $i++) { $a = $dte.Debugger.GetExpression("departments[$i].OrgagnizationalRoleId"); Write-Host $a.Value $i }
Den Autor der Idee finden Sie hier
Um Ihre Frage zu beantworten, finden Sie hier die offizielle Erklärung des Visual Studio-Programmmanagers, warum Sie dies nicht tun können. Kurz gesagt, weil "es wirklich sehr, sehr schwer ist", in VS zu implementieren. Die Funktion ist jedoch derzeit in Bearbeitung (Stand: August 2014).
Ermöglichen Sie die Auswertung von Lambda-Ausdrücken während des Debuggens
Fügen Sie Ihre Stimme hinzu, während Sie dort sind!