Delegaci w C# oferują podobną funkcjonalność co wskaźniki funkcji w C. Słyszałem, że ktoś mówi: "Delegaci C# są w rzeczywistości lepsi niż wskaźniki funkcji w C". Dlaczego? Proszę wyjaśnić na przykładzie.W jaki sposób delegaci w języku C# są lepsze od wskaźników funkcji w C/C++?
Odpowiedz
"Better" jest subiektywna - ale główne różnice to:
- Typ bezpieczeństwa. Delegat ma nie tylko gwarancję, że odwołuje się do prawidłowej metody, lecz także do metody z prawidłowym podpisem.
- Jest to wskaźnik metody związany z . Oznacza to, że uczestnik może wskazywać na konkretny obiekt, do którego ma zostać wywołany delegat. Zatem delegat
Action<string>
może odnosić się doalice.GetName
lubbob.GetName
, a nie tylkoPerson.GetName
. Ten może być podobny do C++ "wskaźnik do elementu" - nie jestem pewien.
Ponadto język C# obsługuje zamknięcia za pośrednictwem delegatów do metod anonimowych i wyrażeń lambda - tj. Przechwytywanie zmiennych lokalnych procedury deklarowania, które delegat może odwoływać się, gdy zostanie później wykonane. Nie jest to ściśle funkcja delegatów - jest ona włączona przez kompilator C#, który robi magię na anonimowych metodach i wyrażeniach lambda - ale wciąż jest wart wspomnienia, ponieważ umożliwia wiele funkcjonalnych idiomów w języku C#.
EDIT: W CWF zauważa w komentarzach, inny możliwy zaletą C# delegatów jest, że deklaracje typu delegat są łatwiejsze dla wielu ludzi do czytania. Oczywiście może to być kwestia znajomości i doświadczenia.
Bezpieczeństwo typu: Czy nie ma to miejsca w przypadku wszystkich rodzajów wskaźników w języku C/C++? Czy nie chodzi o kompilator, którego używamy? Mam na myśli, jeśli mój kompilator zgłasza błąd, jeśli wskażę wskaźnik funkcji na int. Czy nie byłoby to bezpieczne? – pecker
Nie, ponieważ możesz zadeklarować wskaźnik do 'int f (int)', ustaw go na adres 'int f (int)', a następnie przesuń go do 'char * f (long)'. Lub 'void * badptr =" losowe śmieci "; INT_FN ohno = (INTFN) badptr; int pwned = ohno (123); '(gdzie INTFN jest typedef dla' int f (int) ', po prostu nie pamiętam składni deklaracji C++ \ * grin \ *). Podczas gdy C# zawiedzie złego rzutu. – itowlson
Bezpieczeństwo typu jest bardziej kwestią języka niż określoną cechą języka. To powiedziawszy, jedyną myślą, że pominąłeś, jest składnia. Deklaracje funkcji w C (i prawdopodobnie C++, gdy nie używa się Boost) mogą być trudne do rozwikłania. Ale deklaracje delegatów są łatwe. Ponadto, lambda jest szczególnym przypadkiem delegatów (jak sądzę) i są one czasami bardzo bardzo przydatne. – CWF
Wskaźniki zawsze wskazują niewłaściwe miejsce :) Może to wskazywać na niefunkcjonalne lub arbitralne miejsce w pamięci.
Ale pod względem funkcjonalności wskaźniki funkcji mogą robić wszystko, co delegaci mogą zrobić.
Tylko uwaga, że trudno jest przecenić, jak duża jest to transakcja. To, że wskaźnik funkcji C++ jest nadal tylko wskaźnikiem w głąb, pozwala na wszelkiego rodzaju zło pod względem nakłaniania do wskazania złośliwego kodu. W przeciwnym razie niepozorny przepełnienie bufora może nagle stać się znacznie łatwiejsze do wykorzystania. –
Joel, bez kłótni z tobą! Myślę, że to główna zaleta Javy nad C++ - wyeliminowanie wskaźników oznaczało wyeliminowanie całego mnóstwa: roblemów. –
Jedna rzecz, którą delegat zapewnia, że wskaźnik funkcji C/C++ nie jest bezpiecznym typem. Oznacza to, że w C/C++ można przesunąć wskaźnik funkcji do zmiennej wskaźnika funkcji zadeklarowanej przy użyciu niewłaściwej sygnatury funkcji (lub nawet podwójnej lub gorszej z odpowiednim koaksowaniem), a kompilator z przyjemnością przygotuje kod wywołujący funkcja całkowicie niepoprawna. W języku C# podpis typu funkcji musi być zgodny z typem podpisu delegata, a także z ostatecznym sposobem wywoływania delegata.
Czy nie jest tak w przypadku wszystkich rodzajów wskaźników w C/C++? Czy nie chodzi o kompilator, którego używamy? Mam na myśli, jeśli mój kompilator zgłasza błąd, jeśli wskażę wskaźnik funkcji na int. Czy nie byłoby to bezpieczne? – pecker
Cóż, na pewno. Twój kompilator może ostrzec cię, gdy przypadkowo spróbujesz umieścić coś w gnieździe, którego nie powinno się zmieścić. Nie twierdzę, że nie powinieneś używać wskaźników funkcji, jeśli piszesz kod w C++ - czasami jest to właściwy język do tego, co robisz. – sblom
Wiele osób odwołuje się do delegatów C# jako bardziej "bezpiecznych" niż do wskaźników funkcyjnych C++ i naprawdę uważam, że jest to mylące. W rzeczywistości nie są bardziej bezpieczne dla typów, ponieważ są wskaźnikami funkcji C++. Przykładem C++ kod (skompilowane przez MSVS 2005 SP1):
typedef int (*pfn) (int);
int f (int) {
return 0;
}
double d (int) {
return 1;
}
int main()
{
pfn p=f; // OK
p=d; // error C2440: '=' : cannot convert from 'double (__cdecl *)(int)' to 'pfn'
p=(pfn)d;
}
Więc jak widać z powyższego przykładu, chyba że ktoś używa „brudnych hacków” do „shut up” kompilator niedopasowanie typu jest łatwy do wykrycia i kompilator wiadomość jest łatwa do zrozumienia. To jest bezpieczeństwo typu, jak rozumiem.
Odnośnie do "granicy" wskaźników funkcji pręta. Rzeczywiście, w C++ wskaźnik do elementu nie jest powiązany, wskaźnik funkcji elementu musi być zastosowany do zmiennej typu , która pasuje do sygnatury wskaźnika elementu. Przykład:
class A {
public:
int f (int) {
return 2;
}
};
typedef int (A::*pmfn) (int);
int main()
{
pmfn p=&(A::f);
// Now call it.
A *a=new A;
(a->*p)(0); // Calls A::f
}
Znowu wszystko jest idealnie bezpieczne.
Wpisz bezpieczny, aby rzucić do "void *" iz powrotem. Wtedy ten wskaźnik będzie wyglądał tak, jak chcesz, ale pęknie, gdy spróbujesz go użyć. C# sprawia, że takie oszustwo jest bardzo trudne, jeśli nie niemożliwe. – cHao
@CHao nope, C++ nie zezwala na niejawną konwersję z void * na inną * (umożliwia niejawną konwersję w innym kierunku). To C, o którym mówisz. Co do tego, że takie sztuczki są trudne (nie ma mowy, że w piekle jest to niemożliwe), myślę, że to przesada, po prostu nie rób tego przez przypadek i pozostaw resztę programistom (tj. Ufaj, że programiści używają swojego mózgu). – Giel
- 1. W jaki sposób delegaci poprawiają wydajność aplikacji?
- 2. Delegaci w C# i FNC wskaźniki w C++
- 3. Jaki jest cel delegatów są niezmienne w języku C#?
- 4. Tablica wskaźników funkcji w C
- 5. Okólnik w języku C++ bez wskaźników
- 6. C składnia funkcji powracających wskaźników funkcji
- 7. substytut wskaźników funkcji w python
- 8. w jaki sposób uczynić pip zgodnym ze zmienną środowiskową "CC"
- 9. Wydarzenia/Delegaci W Javie lub C#
- 10. Odtwarzaj tablicę wskaźników funkcji C w Pythonie
- 11. C# Func <> delegaci w bibliotece
- 12. Jak zapisać wskaźnik funkcji w języku C#
- 13. Korzystanie ze wskaźników znalezionych w Cheat Engine w języku C#
- 14. W jaki sposób realizowane są generatory i coroutines w CPython?
- 15. W jaki sposób FileAttributes.Encrypted działa w języku C#?
- 16. W jaki sposób extern działa w języku C++?
- 17. przekazywanie wskaźników do extern funkcji C w DLL z VB
- 18. W jaki sposób pojęcie statyczne w języku Java różni się od C#?
- 19. W jaki sposób są pakowane małe typy danych w C#
- 20. Przekazywanie niezarządzanych wskaźników w C++/CLI
- 21. lepsze zrozumienie zewnętrznych funkcji "C"
- 22. Przesłanianie funkcji w języku Java vs C++
- 23. Przechowywanie funkcji SYSCALL w tablicy wskaźników funkcji
- 24. W języku C# są obiekty Lambda Expressions?
- 25. Właściwy sposób na posiadanie wskaźników funkcji w struct
- 26. W języku Erlang, w jaki sposób wywołujesz funkcję dynamicznie?
- 27. W jaki sposób sygnał i gniazda są zaimplementowane pod maską?
- 28. Jaki jest najlepszy sposób rekurencyjnego kopiowania zawartości w języku C#?
- 29. W jaki sposób zmienne są przechowywane w pamięci w rekursji?
- 30. C++: Używanie wskaźników funkcji z funkcjami składowymi
Kto powiedział, że może lepiej wyjaśnić, co przez to rozumieją, nie? – Victor
Właściwie to czytam w długiej książce. Nie pamiętam, która książka. Ale teraz używam wskaźników funkcji w moim kodzie C. Tak, właśnie zapamiętany. – pecker
Jest to silnie typowany typ danych pierwszej klasy (jak klasa) i można również zdefiniować delegata wbudowanego. Jest to pewien postęp w kierunku wskaźnika funkcji w C/C++. –