2009-02-24 9 views
11

Tak więc, za każdym razem, gdy napisałem wyrażenie lambda lub metodę anonimową w metodzie, której nie uzyskałem całkiem od razu, jestem zmuszony do przekompilowania i zrestartowania całej frameworka aplikacji lub jednostki testowej w celu jej poprawienia. Jest to bardzo denerwujące i ostatecznie tracę więcej czasu niż zaoszczędziłem, wykorzystując te konstrukcje w pierwszej kolejności. Jest tak źle, że staram się trzymać z dala od nich, jeśli mogę, mimo że Linq i lambdas są jednymi z moich ulubionych funkcji C#.Dlaczego nie mogę edytować metody zawierającej anonimową metodę w debugerze?

Przypuszczam, że istnieje dobry techniczny powód, dlaczego tak się dzieje i być może ktoś wie? Ponadto, czy ktoś wie, czy zostanie on poprawiony w VS2010?

Dzięki.

Odpowiedz

14

Tak, istnieje bardzo dobry powód, dla którego nie można tego zrobić. Prostym powodem są koszty. Koszt włączenia tej funkcji w języku C# (lub VB) wynosi wyjątkowo wysoki:.

Edycja funkcji lambda jest specyficznym przypadkiem klasy problemów ENC, które są bardzo trudne do rozwiązania przy obecnej architekturze ENC (Edit'n'Continue). Mianowicie, jest to bardzo trudne do ENC każda metoda, która gdzie ENC ma jedną z następujących czynności: -

  1. Generuje metadane w postaci klasy
  2. Edycje lub generuje ogólną metodę

pierwsze wydanie jest raczej ograniczeniem logicznym, ale także wpada w kilka ograniczeń w architekturze ENC. Mianowicie problem generowania pierwszej klasy nie jest strasznie trudny. To, co przeszkadza, to generowanie klasy po drugiej edycji. Silnik ENC musi rozpocząć śledzenie tabeli symboli nie tylko pod kątem kodu na żywo, ale także wygenerowanych klas. Zwykle nie jest tak źle, ale staje się to coraz trudniejsze, gdy kształt generowanej klasy jest oparty na kontekście, w którym jest używany (tak jak w przypadku lambdas z powodu zamknięć). Co ważniejsze, w jaki sposób rozwiązujesz różnice w stosunku do instancji klas, które już są aktywne w procesie?

Druga kwestia to ścisłe ograniczenie architektury CLR ENC. Nie ma nic, co C# (lub VB) może zrobić, aby obejść to.

Niestety Lambdas trafił w oba te problemy. Krótka wersja jest taka, że ​​ENC'ing lambda obejmuje wiele mutacji na istniejących klasach (które mogą lub nie zostały wygenerowane z innych ENC). Duży problem polega na rozwiązaniu różnic między nowym kodem a istniejącymi instancjami zamykającymi, które są żywe w obecnej przestrzeni procesowej. Ponadto lambdy często używają generycznych o wiele więcej niż inne kody i trafiają w numer 2.

Szczegóły są dość owłosione i nieco zbyt zaangażowane, aby uzyskać zwykłą odpowiedź na WR. Rozważałem napisanie długiego blogu na ten temat. Jeśli się do tego zabiorę, powiążę go z tą konkretną odpowiedzią.

+1

Prosto z ust konia. +1 –

+0

@Jon Mieliśmy wiele wewnętrznych spotkań na ten temat i musiałem wielokrotnie prezentować tę prezentację. Naprawdę muszę napisać pełny dokument na ten temat. Blogowanie wydaje się dobrym miejscem na to. Istnieje nadzieja, że ​​zostanie to rozwiązane w przyszłej wersji VS. – JaredPar

+1

Napisz o tym blogu. – Eyvind

0

Ponowne uruchomienie testu urządzenia powinno zająć kilka sekund. Nigdy nie lubiłem modelu "edytuj i kontynuuj", mówiąc szczerze - powinieneś zawsze uruchamiać od podstaw IMO, na wypadek gdyby zmiana w trakcie wykonywania wpłynęła na kod, który działał wcześniej. Biorąc to pod uwagę, lepiej jest korzystać z testów jednostkowych, które można uruchomić bardzo szybko. Jeśli twoje indywidualne testy jednostkowe zajmują niewiarygodny czas, to powinieneś spojrzeć na adresowanie.

EDYCJA: Co do tego, dlaczego nie działa - może się okazać, że działa dla niektórych lambd, ale nie dla innych. Wyrażenia lambdy, które nie przechwytują żadnych zmiennych (w tym this), są buforowane w prywatnej zmiennej statycznej, tak że tworzone jest tylko jedno wystąpienie delegata. Zmiana kodu oznacza reinicjację tej zmiennej, która może mieć interesujące efekty uboczne, które podejrzewam.

+0

Zgadzam się ...., ale to nie jest odpowiedź na pytanie. –

+0

Wiedziałem, że znasz odpowiedź ;-) –

+0

IMO odpowiedzią na wiele pytań jest uniknięcie wejścia w bolesną sytuację. –

1

Zgodnie z listą Supported Code Changes nie można dodawać pól do istniejących typów. Anonimowe metody są kompilowane do dziwnie nazwanych klas (kinda <>_c__DisplayClass1), które są dokładnie tym: typami. Mimo, że twoje modyfikacje anonimowej metody mogą nie uwzględniać zmiany zestawu załączonych zmiennych (dodanie tych zmieni pola w istniejącej klasie), to jest powód, dla którego nie można modyfikować anonimowych metod.

+1

Nie trzeba modyfikować samej anonimowej metody dla tego problemu, aby się zamanifestować, wystarczy zmodyfikować metodę _contains_ anonymous method i wydaje się, że wystarczy nawet jedna spacja, aby ją usunąć ... – Eyvind

1

jest nieco wstyd, że funkcja ta jest częściowo obsługiwany VB, ale nie w C# http://msdn.microsoft.com/en-us/library/bb385795.aspx

wykonawcze takie samo zachowanie C# zmniejszy poziom bólu o 80% w odniesieniu do funkcji, które zawierają wyrażenia lambda gdzie nie potrzebujemy modyfikować wyrażeń lambda ani żadnego wyrażenia, które zależy od nich i prawdopodobnie nie jest to "koszt potwora".

Powiązane problemy