Dokuczało mi to przez długi czas, dziś wymyśliłem sposób, aby to zrobić za pomocą drzewek wyrażeń w .NET 4.0.
Rozważmy następujący kod:
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);
}
Teraz - Jestem w stanie wywołać ten kod bez wahania - jedyne miejsce debugger będzie próbował powstrzymać jest łamaną własności pochłaniacza borked za - dlatego dodałem tam atrybut DebuggerStepThrough
.
Zamiast przyjmować lambdę, biorę drzewo wyrażeń (które używa tej samej składni!), I kompiluję je i uruchamiam w czasie wykonywania - to jest trochę więcej pracy (ledwo) niż użycie regularna lambda, i nie będzie działać na wszystko, ale dla prostych zapytań Linq i takie, działa świetnie.
Cała magia dzieje się w następujący sposób - który, ponownie, pierwotnie używany do przyjęcia zwykłego argumentu Func<>
- ale że zatrzymał debugger, gdy został zgłoszony wyjątek (mimo atrybutu krokowego), więc teraz mam zrobić z Expression<Func<>>
tak:
[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;
}
Zgadza się - wystarczy zadzwonić .Compile()
i oddanych zwracanej wartości do regularnego Func<>
które można natychmiast powołać !! - Jakie to łatwe ?!
W mojej implementacji pozwoliłem użytkownikowi przekazać wiele parametrów, dzięki czemu mogą uzyskać wartość rezerwową (i że ta wartość zastępcza jest tworzona/oceniana tylko jako IF).
Nie jestem również pewien, czy przyczyną tłumienia zdarzenia debugowania jest "Just my Code" VisualStudio, czy dlatego, że jest on uruchamiany inline w tej metodzie ..., ale tak czy inaczej to działa dziwnie , cholera!!
Teraz zgaduję, że wywołanie tej metody w czasie wykonywania nie jest superszybkie, ale w praktyce nie wydaje mi się, aby w moich kwerendach dodawałem dla mnie jakiekolwiek obniżenie wydajności. Jestem bardzo podekscytowany (proszę wybaczyć wielokrotne/zbędne grzywki i interwangi itp.)
Kiedy to się kończy? Klikasz go w krok na początku funkcji GetA()? Czy jest punkt przerwania? co to znaczy, że zatrzymuje się na "a.b == b"? – tster
Zwykle używałbyś klawisza F10 do przechodzenia przez funkcję. Dlaczego nie chcesz użyć F10 w tym przypadku? –
Zwykle używałbyś F11 podczas debugowania bez zastanawiania się, jaką kombinację klawiszy użyć F11 lub F10. DebuggerStepThrough bardzo pomaga, ale nie zawsze. – drumsta