Poniższy kod zawiera metodę statyczną Foo()
, wywołując metodę instancji Bar()
:
public sealed class Example
{
int count;
public static void Foo( dynamic x )
{
Bar(x);
}
void Bar( dynamic x )
{
count++;
}
}
Kompiluje się bez błędów *, ale generuje wyjątek spinacza czasu wykonywania w czasie wykonywania. Zgodnie z oczekiwaniami usunięcie parametru dynamicznego z tych metod powoduje błąd kompilatora.
Dlaczego więc posiadanie parametru dynamicznego pozwala na kompilację kodu? ReSharper również nie pokazuje tego jako błędu.
Edytuj 1: * w programie Visual Studio 2008
Edycja 2: dodana, sealed
ponieważ jest możliwe, że podklasa może zawierać Bar(...)
metodę statyczną . Nawet wersja zapieczętowana kompiluje się, gdy nie jest możliwe wywołanie metody innej niż metoda instancji w czasie wykonywania.
c#
visual-studio-2008
dynamic
compiler-errors
Mike Scott
źródło
źródło
dynamic
chyba że naprawdę potrzebujesz.Odpowiedzi:
AKTUALIZACJA: Poniższa odpowiedź została napisana w 2012 roku, przed wprowadzeniem C # 7.3 (maj 2018) . W Co nowego w C # 7,3 , w sekcji Ulepszeni kandydaci na przeciążenie , element 1, wyjaśniono, w jaki sposób zmieniły się reguły rozpoznawania przeciążenia, tak że niestatyczne przeciążenia są wcześnie odrzucane. Tak więc poniższa odpowiedź (i całe to pytanie) ma teraz głównie znaczenie historyczne!
(Przed C # 7.3 :)
Z jakiegoś powodu rozpoznawanie przeciążenia zawsze znajduje najlepsze dopasowanie przed sprawdzeniem statycznej i niestatycznej. Spróbuj tego kodu ze wszystkimi statycznymi typami:
To się nie skompiluje, ponieważ najlepszym przeciążeniem jest ten, który pobiera plik
string
. Ale hej, to jest metoda instancji, więc kompilator narzeka (zamiast pobierać drugie w kolejności przeciążenie).Dodatek: Myślę więc, że wyjaśnienie
dynamic
przykładu pierwotnego pytania jest takie, że aby zachować spójność, gdy typy są dynamiczne, najpierw znajdujemy również najlepsze przeciążenie (sprawdzanie tylko liczby parametrów i typów parametrów itp., A nie statyczne vs. nie -static), a dopiero potem sprawdź, czy jest statyczny. Ale to oznacza, że kontrola statyczna musi czekać do czasu uruchomienia. Stąd obserwowane zachowanie.Późne dodanie: Z tego posta na blogu Erica Lipperta można wywnioskować, dlaczego zdecydowali się robić rzeczy w tej zabawnej kolejności .
źródło
dynamic
został wprowadzony w języku, myślę, że projektanci C # powiedzieli: „Nie będziemy rozważać (2) czasu kompilacji, gdy jest todynamic
wyrażenie”. Więc moim celem jest tutaj wymyślenie, dlaczego zdecydowali się nie sprawdzać statycznej i instancji do czasu wykonania. Powiedziałbym, że to sprawdzenie odbywa się w czasie wiązania .Foo ma parametr „x”, który jest dynamiczny, co oznacza, że Bar (x) jest wyrażeniem dynamicznym.
W przypadku przykładu byłoby całkowicie możliwe zastosowanie metod takich jak:
W takim przypadku poprawna metoda zostanie rozwiązana, więc instrukcja Bar (x) jest całkowicie poprawna. Fakt, że istnieje metoda instancji Bar (x) jest nieistotny i nawet nie brany pod uwagę: z definicji , ponieważ Bar (x) jest wyrażeniem dynamicznym, odłożyliśmy rozstrzygnięcie do czasu wykonania.
źródło
Wyrażenie „dynamiczne” będzie związane w czasie wykonywania, więc jeśli zdefiniujesz metodę statyczną z poprawnym podpisem lub metodą instancji, kompilator nie będzie tego sprawdzał.
„Właściwa” metoda zostanie określona w czasie wykonywania. Kompilator nie może wiedzieć, czy w czasie wykonywania jest tam prawidłowa metoda.
Słowo kluczowe „dynamic” jest zdefiniowane dla języków dynamicznych i skryptowych, w których Metodę można zdefiniować w dowolnym momencie, nawet w czasie wykonywania. Zwariowane rzeczy
Tutaj przykład, który obsługuje ints, ale bez łańcuchów, ze względu na metodę, znajduje się w instancji.
Możesz dodać metodę obsługi wszystkich „złych” wywołań, których nie można obsłużyć
źródło