Dies störte mich lange, heute habe ich einen Weg gefunden, dies mit Hilfe von Expression-Bäumen in .NET 4.0 zu tun.
Betrachten Sie den folgenden Code ein:
private class Borked
{
public object X
{
[DebuggerStepThrough]
get { throw new NotImplementedException(); }
}
}
private void SomeMethod()
{
var bad = new Borked();
object obj = bad.TryGet(o => o.X);
}
jetzt - ich bin in der Lage diesen Code aufrufen, ohne aus dem Takt - der einzige Ort, der Debugger in borked gebrochenes Getter Eigenschaft zu stoppen versuchen würde, ist - deshalb habe ich das Attribut DebuggerStepThrough
dort hinzugefügt.
Statt in einem Lambda zu nehmen, nehme ich in einem Ausdrucksbaum (die die gleiche Syntax verwendet !!), und ich kompilieren und zur Laufzeit ausgeführt werden - es ist ein wenig mehr Arbeit (gerade noch) als eine mit reguläres Lambda, und es wird nicht für alles funktionieren, aber für einfache Linq-Abfragen und so funktioniert es großartig.
All die Magie passiert in der folgenden Methode - die wiederum ursprünglich ein normales Func<>
Argument akzeptiert - aber das Debugger angehalten, wenn eine Ausnahme ausgelöst wurde (trotz der Step-through-Attribut), so jetzt ich tun Sie es mit einem Expression<Func<>>
etwa so:
[DebuggerStepThrough]
public static T TryGet<OT, T>(this OT obj, params Expression<Func<OT, T>>[] getters)
{
T ret = default(T);
if (getters != null)
{
foreach (var getter in getters)
{
try
{
if (getter != null)
{
var getter2 = (Func<OT, T>)getter.Compile();
ret = getter2(obj);
break;
}
}
catch
{ /* try next getter or return default */ }
}
}
return ret;
}
das ist richtig - man muss nur .Compile()
anrufen und den Rückgabewert zu einem regulären Func<>
werfen, die Sie sofort aufrufen können !! - Wie einfach war das ?!
In meiner Implementierung ließ ich den Benutzer mehrere Parameter übergeben, so dass sie einen Fallback-Wert erhalten können (und dass dieser Fallback-Wert nur erstellt/ausgewertet wird IF erforderlich).
Auch bin ich nicht sicher, ob der Debug-Ereignis unterdrückt wird, ist wegen VisualStudio "Just my Code", oder weil es inline in dieser Methode ausgeführt wird ..., aber so oder so funktioniert es , dang es !!
Nun, ich vermute, dass Aufruf der .Compile
Methode auf den Ausdruck zur Laufzeit ist nicht super schnell, aber in der Praxis scheint es keine Leistungseinbußen für mich in meinen Abfragen hinzuzufügen. Also, ich bin ziemlich aufgeregt (bitte entschuldigen Sie die multiplen/redundanten Pony und Interobangs, etc.)
Wann hört es dort auf? Klicken Sie in einem Schritt auf den Anfang der Funktion GetA()? Gibt es einen Haltepunkt? Was meinst du damit, dass es bei "a.b == b" aufhört? – tster
Normalerweise würden Sie F10 verwenden, um eine Funktion zu überspringen. Warum willst du in diesem Fall nicht F10 benutzen? –
Normalerweise würden Sie F11 während des Debuggens verwenden, ohne darüber nachzudenken, welche Tastenkombination für F11 oder F10 verwendet wird. DebuggerStepThrough hilft sehr, aber nicht immer. – drumsta