Jak wykonywać „funkcje wbudowane” w języku C #? Nie sądzę, że rozumiem tę koncepcję. Czy są jak anonimowe metody? Jak funkcje lambda?
Uwaga : odpowiedzi prawie w całości dotyczą możliwości wstawiania funkcji , tj. „Optymalizacji ręcznej lub kompilatora, która zastępuje witrynę wywołania funkcji ciałem odbiorcy”. Jeśli interesują Cię anonimowe (aka lambda) funkcje , zobacz odpowiedź @ jalfa lub o czym jest ta „Lambda”, o której wszyscy mówią? .
c#
optimization
inline
Dina
źródło
źródło
Odpowiedzi:
Wreszcie w .NET 4.5 CLR pozwala wskazać / zasugerować wprowadzenie 1 metody za pomocą
MethodImplOptions.AggressiveInlining
wartości. Jest on również dostępny w bagażniku Mono (zatwierdzony dzisiaj).1 . Wcześniej używano tutaj „siły”. Ponieważ było kilka głosów negatywnych, postaram się wyjaśnić ten termin. Podobnie jak w komentarzach i dokumentacji,
The method should be inlined if possible.
szczególnie biorąc pod uwagę Mono (który jest otwarty), istnieją pewne techniczne ograniczenia mono-specyficzne, biorąc pod uwagę wbudowanie lub bardziej ogólne (takie jak funkcje wirtualne). Ogólnie tak, jest to wskazówka dla kompilatora, ale myślę, że o to poproszono.źródło
Metody inline to po prostu optymalizacja kompilatora, w której kod funkcji jest wprowadzany do programu wywołującego.
Nie ma mechanizmu, dzięki któremu można to zrobić w języku C #, i powinny być używane oszczędnie w językach, w których są obsługiwane - jeśli nie wiesz, dlaczego powinny być gdzieś używane, nie powinny.
Edycja: Aby wyjaśnić, istnieją dwa główne powody, dla których należy je stosować oszczędnie:
Najlepiej zostawić wszystko w spokoju i pozwolić kompilatorowi wykonać swoją pracę, a następnie profilować i zastanowić się, czy inline jest najlepszym rozwiązaniem dla Ciebie. Oczywiście, niektóre rzeczy mają sens, aby je wprowadzić (szczególnie operatory matematyczne), ale pozwolenie kompilatorowi na obsługę tego jest zwykle najlepszą praktyką.
źródło
Aktualizacja: Zgodnie z odpowiedzią konrad.kruczynski , poniższe są prawdziwe dla wersji .NET do wersji 4.0 włącznie.
Możesz użyć metody MethodImplAttribute, aby zapobiec wstawianiu metody ...
... ale nie ma sposobu, aby zrobić coś przeciwnego i zmusić go do podkreślenia.
źródło
GetExecutingAssembly
iGetCallingAssembly
może dawać różne wyniki w zależności od tego, czy metoda jest wbudowana. Wymuszenie braku wbudowania metody eliminuje wszelką niepewność.Mieszacie dwie odrębne koncepcje. Inlining funkcji to optymalizacja kompilatora, która nie ma wpływu na semantykę. Funkcja zachowuje się tak samo, niezależnie od tego, czy jest wstawiana, czy nie.
Z drugiej strony funkcje lambda są czysto semantycznym pojęciem. Nie ma wymagań dotyczących sposobu ich implementacji lub wykonania, pod warunkiem, że zachowują się one zgodnie ze specyfikacją języka. Można je wstawić, jeśli kompilator JIT ma na to ochotę, lub nie, jeśli tak nie jest.
W języku C # nie ma wbudowanego słowa kluczowego, ponieważ jest to optymalizacja, którą zwykle można pozostawić kompilatorowi, szczególnie w językach JIT. Kompilator JIT ma dostęp do statystyk środowiska wykonawczego, co pozwala mu decydować, co wstawiać znacznie wydajniej niż jest to możliwe podczas pisania kodu. Funkcja zostanie wstawiona, jeśli kompilator podejmie taką decyzję, i nic nie możesz na to poradzić. :)
źródło
Masz na myśli funkcje wbudowane w sensie C ++? W którym zawartość normalnej funkcji jest automatycznie kopiowana bezpośrednio do strony wywoławczej? Efektem końcowym jest to, że podczas wywoływania funkcji nie dzieje się żadne wywołanie funkcji.
Przykład:
Jeśli tak, to nie, nie ma C # równoważnego z tym.
Czy masz na myśli funkcje zadeklarowane w ramach innej funkcji? Jeśli tak, to tak, C # obsługuje to za pomocą anonimowych metod lub wyrażeń lambda.
Przykład:
źródło
Cody ma rację, ale chcę podać przykład tego, czym jest funkcja wbudowana.
Powiedzmy, że masz ten kod:
KompilatorJust-In-Time optymalizator mogli wybrać, aby zmienić kod wielokrotnie unikać umieszczania wezwanie do OutputItem () na stosie, tak, że będzie tak, jakbyś napisał kod jak to w zamian:W takim przypadku powiedzielibyśmy, że funkcja OutputItem () została wstawiona. Zauważ, że może to zrobić, nawet jeśli OutputItem () jest wywoływany również z innych miejsc.
Edytowane, aby pokazać scenariusz, który może zostać wstawiony.
źródło
Tak Dokładnie, jedynym rozróżnieniem jest fakt, że zwraca wartość.
Uproszczenie (bez użycia wyrażeń):
List<T>.ForEach
Podejmuje akcję, nie oczekuje zwrotu.Tak więc
Action<T>
wystarczyłby delegat ... powiedz:to to samo co powiedzenie:
Różnica polega na tym, że typ parametru i decelacja delegata są wywnioskowane na podstawie użycia, a nawiasy klamrowe nie są wymagane w prostej metodzie inline.
Natomiast
List<T>.Where
Pełni funkcję, oczekując wyniku.Więc
Function<T, bool>
można by się spodziewać:który jest taki sam jak:
Możesz również zadeklarować te metody bezpośrednio i przypisać je do zmiennych IE:
lub
Mam nadzieję, że to pomoże.
źródło
Są sytuacje, w których chcę wymusić wstawienie kodu.
Na przykład, jeśli mam złożoną procedurę, w której w bardzo iteracyjnym bloku podejmowanych jest wiele decyzji, które skutkują podobnymi, ale nieco różniącymi się działaniami do wykonania. Rozważmy na przykład złożony moduł porównujący sortowanie (nie oparty na bazie danych), w którym algorytm sortujący sortuje elementy według szeregu różnych niepowiązanych kryteriów, takich jak na przykład sortowanie słów według kryteriów gramatycznych i semantycznych szybkiego języka system rozpoznawania. Miałem tendencję do pisania funkcji pomocniczych do obsługi tych akcji w celu utrzymania czytelności i modułowości kodu źródłowego.
Wiem, że te funkcje pomocnicze powinny być wbudowane, ponieważ w taki sposób kod zostałby napisany, gdyby człowiek nigdy nie musiał go rozumieć. Z pewnością chciałbym w tym przypadku upewnić się, że nie będzie narzutów wywołujących funkcji.
źródło
Stwierdzenie „najlepiej zostawić te rzeczy w spokoju i pozwolić kompilatorowi wykonać pracę ...” (Cody Brocious) jest kompletnym rubinem. Programuję wysokowydajny kod do gry od 20 lat i jeszcze nie spotkałem się z kompilatorem, który jest „wystarczająco inteligentny”, aby wiedzieć, który kod należy wstawić (funkcje), czy nie. Przydałoby się mieć instrukcję „inline” w języku c #, prawda jest taka, że kompilator po prostu nie ma wszystkich informacji potrzebnych do ustalenia, która funkcja powinna być zawsze wstawiana, czy nie bez wskazówki „inline”. Jasne, że jeśli funkcja jest mała (akcesor), może być automatycznie wstawiana, ale co, jeśli jest to kilka wierszy kodu? Bez sensu, kompilator nie ma możliwości wiedzieć, nie możesz po prostu zostawić tego kompilatorowi w zakresie zoptymalizowanego kodu (poza algorytmami).
źródło
Wiem, że to pytanie dotyczy C #. Można jednak pisać funkcje wbudowane w .NET za pomocą F #. patrz: użycie „inline” w F #
źródło
Nie, nie ma takiej konstrukcji w języku C #, ale kompilator .NET JIT może zdecydować o wykonywaniu wbudowanych funkcji w czasie JIT. Ale tak naprawdę nie wiem, czy naprawdę robi takie optymalizacje.
(Myślę, że powinien :-))
źródło
W przypadku, gdy twoje zespoły będą ngenowane, możesz rzucić okiem na TargetedPatchingOptOut. Pomoże to Ngen zdecydować, czy wstawić metody.Odniesienie MSDN
Jest to jednak tylko deklaratywna wskazówka do optymalizacji, a nie polecenie nakazowe.
źródło
Wyrażenia lambda są funkcjami wbudowanymi! Myślę, że C # nie ma dodatkowego atrybutu takiego jak inline lub coś takiego!
źródło
C # nie obsługuje wbudowanych metod (lub funkcji) w sposób, w jaki robią to dynamiczne języki, takie jak Python. Jednak anonimowych metod i lambd można używać do podobnych celów, w tym gdy trzeba uzyskać dostęp do zmiennej w metodzie zawierającej, jak w poniższym przykładzie.
źródło