Wady używania typów dynamicznych w C #

14

Ostatnio studiowałem więcej na temat typów dynamicznych w C #. W niektórych przykładach zrozumiałem, że po skompilowaniu kod nie wymaga ponownej kompilacji, ale można go wykonać bezpośrednio.

Uważam, że elastyczność zapewniana przez słowo kluczowe w celu faktycznej zmiany typu danych do woli jest wielką zaletą .

Pytanie,

Czy są jakieś specyficzne niedociągnięcia oprócz niewłaściwych wywołań metod dynamicznych, które rzucają wyjątki czasu wykonywania, które programiści muszą znać przed rozpoczęciem implementacji.

Karthik Sreenivasan
źródło
3
W C # 3 zawsze uważałem użycie objectrzutowania typu bezpośredniego za zapach kodowy. W prawie każdym przypadku oznaczało to, że ja lub jeden z moich zespołów nie zaprojektowałem odpowiedniego interfejsu dla tej funkcjonalności. Zgaduję, że gdybym teraz używał C # 4, czułbym się w ten sam sposób dynamic. Mogę to zobaczyć, jeśli sprawisz, że wszystko stanie się dynamiczne, ale w takim przypadku możesz równie dobrze wybrać dynamiczny język maszynowy. * 8 ')
Mark Booth
@MarkBooth +1 dla perspektywy. Czy można zatem bezpiecznie powiedzieć, że podstawowa implementacja korzystająca z C # pozostanie silnie napisana pomimo wprowadzenia dynamicznych typów w 4.0
Karthik Sreenivasan
Używanie dynamicw C # oznacza, że ​​nie musisz rezygnować z IronPython, jeśli potrzebujesz tylko dynamicznego pisania dla małej części kodu. Dla ewaluatora wyrażeń miałem duży sukces dynamicw reprezentowaniu operandów wyrażenia i wyników oceny.
Ed James
@EdJames - To brzmi jak świetne zastosowanie dynamic, a ponadto chciałbym wiedzieć o IronPython, kiedy tworzyłem z .Net - mogło to ułatwić pewne rzeczy, które staraliśmy się zrobić znacznie łatwiej.
Mark Booth
Zobacz stackoverflow.com/questions/31859016/…
nic nie jest potrzebne

Odpowiedzi:

16

Główną wadą jest to, że wyrzucasz jedną z głównych właściwości (niekoniecznie zalet) C # - że jest on statycznie wpisany (a dla większości typów bezpieczny).

Problem z dynamicznym pisaniem polega na tym, że często ukrywa błędy, które w innym przypadku zostałyby ujawnione podczas kompilacji. Taki błąd pojawia się wtedy tylko w czasie wykonywania, co oczywiście znacznie utrudnia jego wykrycie.

IMO ma bardzo niewiele powodów, aby używać pisania dynamicznego w C #, z których głównym jest współpraca z językami dynamicznie wpisywanymi (którym jest AFAIK, ponieważ dynamika została wprowadzona w pierwszej kolejności).

Jeśli chcesz wykonywać w pełni dynamiczne programowanie, powinieneś spojrzeć na język, który jest zaprojektowany tak, aby był dynamiczny, a nie hakować C #, aby być dynamicznym. Możesz użyć na przykład IronPython, jeśli chcesz korzystać z bibliotek .Net

Matěj Zábský
źródło
+1 dla IronPython. Oznacza to, że w dłuższej perspektywie może to prowadzić do problemów konserwacyjnych.
Karthik Sreenivasan
6
Najważniejszą rzeczą, która dynamicdaje ci możliwość podniesienia obiektu do jego rzeczywistego typu bez żadnego hackowania odbicia. Na przykład, jeśli Base foo = new Derived();i tam były dwie metody przeciążony Moo(Base x)i Moo(Derived x), a następnie Moo(foo)zwraca Moo(Base x), ale Moo((dynamic)foo)rozmowy Moo(Derived x). Prowadzi to do bardzo eleganckiej implementacji wzorca gościa, na przykład: code.logos.com/blog/2010/03/... i ogólnie jest bardzo skuteczną techniką.
@TheMouthofaCow Fajnie, z pewnością jest też kilka innych „uzasadnionych” zastosowań dla dynamiki, jednak jest ich niewiele i są daleko od siebie (i zdecydowanie musisz wiedzieć, co robisz, zanim spróbujesz czegoś takiego).
Matěj Zábský
@TheMouthofaCow Do odnotowania stosunkowo nowy wzorzec projektowy (Wzorzec gościa). Dzięki.
Karthik Sreenivasan
1
Tak, to całkiem fajne. Wpadłem na to niezależnie w zeszłym tygodniu, więc miło było zobaczyć, że jest to zaakceptowany pomysł, który został zaadaptowany do arsenału C #.
9

Nie jestem pewien, jakiego rodzaju niedociągnięć szukasz, ale jeśli chcesz wiedzieć o funkcjach, które działają przy pisaniu statycznym, ale nie z dynamic, istnieje kilka:

  1. Metody rozszerzeń nie działają. To chyba największy. Jeśli tak dynamic collection, nie możesz używać kodu podobnego do collection.Distinct(). Jest tak, ponieważ dostępne metody rozszerzenia zależą od przestrzeni nazw, usinga DLR nie ma możliwości ich poznania.

    Jako obejście, można wywołać metodę jakby to była normalna metoda statyczna: Enumerable.Distinct(collection). Lub możesz zmienić typ kolekcji na coś podobnego IEnumerable<dynamic>.

  2. foreachwymaga IEnumerable. W normalnym języku C # foreachjest oparty na wzorcach. Oznacza to, że nie wymaga żadnego konkretnego interfejsu, a jedynie GetEnumerator()metody zwracającej odpowiedni obiekt. Jeśli używasz foreachdalej dynamic, IEnumerablewymagana jest implementacja . Ale ponieważ powodem takiego zachowania jest to, że C # 1.0 nie miał generycznych, to „niedociągnięcie” jest praktycznie nieistotne.

svick
źródło
+1 za metodę rozszerzeń. Czy dotyczy to również innych operatorów zapytań LINQ, takich jak GroupBy ()?
Karthik Sreenivasan
2
@Karthik: Tak. Myślę, że metody rozszerzeń to cukier składniowy w czasie kompilacji, stąd fakt, że nie zostaną rozwiązane.
@TheMouthofaCow +1 - Dziękujemy za wyjaśnienie.
Karthik Sreenivasan
1
Zgadzam się z metodami rozszerzenia, tzn. Jak dynamika nie może zrozumieć metod rozszerzenia w czasie wykonywania, ale nie mogłem śledzić dynamicznej kolekcji, którą wyjaśniłeś.
Karthik Sreenivasan
7

Problem z typami dynamicznymi (nie zmiennymi zadeklarowanymi jako dynamiczne) w .net polega na tym, że nie mają one zbyt wielu funkcji dostępnych dla typów statycznych.

  • nie ma refleksji (możesz iterować nad członkami, ale niewiele więcej)
  • brak metadanych (sprawdzanie poprawności odbywa się w dynamicznych witrynach danych / mvc)
  • absolutnie brak sprawdzania w czasie kompilacji (wszelkie błędy pisowni nie zostaną wyłapane)
  • ponieważ jest to potężna funkcja, nooby mogą mieć tendencję do nadużywania / niewłaściwego używania / niezrozumienia
  • kod napisany typami dynamicznymi jest trudny do utrzymania i cholernie trudny do refaktoryzacji
  • z powodu pisania kaczek i innych funkcji guru mogą pisać kod, który jest nieczytelny dla nikogo innego

Nie pisz więc kodu z typami dynamicznymi, chyba że wiesz, co robisz.

linkerro
źródło
6

Ponieważ dynamicjest to tylko zaznaczone object, zawiera pola typów wartości.

Może to mieć wpływ na wydajność, ale ponieważ i tak używałbym pisania statycznego w kodzie krytycznym pod względem wydajności, prawdopodobnie nie jest to problem w praktyce.

Boks ten zakłóca także zmienne typy wartości. Jeśli je zmodyfikujesz dynamic, zmodyfikujesz tylko kopię w pudełku. Ponieważ jednak nie powinieneś używać zmiennych typów wartości, nie jest to również duży problem.

CodesInChaos
źródło
+1 Zdecydowanie się zgadzam. Najlepszym podejściem do kodu krytycznego dla wydajności byłoby wpisywanie statyczne.
Karthik Sreenivasan