Udostępnij za pośrednictwem


Zmiany w odbiciu wywołują wyjątki interfejsu API

Wyjątki zgłaszane podczas wywoływania interfejsów API wywołania odbicia uległy zmianie.

Poprzednie zachowanie

  • Wcześniej, gdy wywołana metoda zwracająca wartość przy użyciu odwołania zwróciła nullwartość , NullReferenceException element został zgłoszony.

  • W przypadku konstruktorów zostały zgłoszone następujące wyjątki:

  • Gdy null przekazano parametr byref-like bez ref modyfikatora (czyli przekazywanego przez wartość), nie zgłoszono wyjątku, a środowisko uruchomieniowe zastąpiło wartość domyślną wartości null.

Nowe zachowanie

Począwszy od platformy .NET 7:

  • Zamiast zgłaszać wyjątek źródłowy (w tym NullReferenceException i wymienione w poprzednim zachowaniu), TargetInvocationException jest zgłaszany we wszystkich przypadkach po zweryfikowaniu początkowych Invoke() parametrówOutOfMemoryException. Wyjątek wewnętrzny zawiera wyjątek źródłowy.

  • NotSupportedExceptionparametr jest zgłaszany, gdy null jest przekazywany dla parametru przypominającego byref, gdy parametr jest zadeklarowany jako "by value" (czyli nie ref ma modyfikatora). W przypadku powiązanego przypadku, gdy parametr jest przekazywany przez odwołanie (tj. ma ref modyfikator), poprzednie i nowe zachowanie są takie same: NotSupportedException jest zgłaszany.

Wprowadzona wersja

.NET 7

Typ zmiany powodującej niezgodność

Ta zmiana może mieć wpływ na zgodność binarną.

Przyczyna wprowadzenia zmiany

Zgłaszanie TargetInvocationException zamiast wyjątku źródłowego sprawia, że środowisko jest bardziej spójne. Prawidłowo warstwuje wyjątki spowodowane weryfikacją parametrów przychodzących (które nie są opakowane TargetInvocationExceptionz ) w porównaniu z wyjątkami zgłaszanymi z powodu implementacji metody docelowej (które są opakowane). Spójne reguły zapewniają bardziej spójne środowiska w różnych implementacjach środowiska CLR i interfejsów Invoke API.

Zmiana, która ma być zgłaszanaNotSupportedException, gdy typ przypominający byref jest przekazywany do Invoke() interfejsu API, naprawia nadzór nad oryginalną implementacją, która nie zgłosiła. Oryginalna implementacja dała wygląd obsługiwany ref struct przez Invoke() interfejsy API, gdy nie są obsługiwane. Ponieważ bieżące Invoke() interfejsy API są używane System.Object dla typów parametrów i ref struct nie można wpisać typu do System.Object, jest to nieobsługiwany scenariusz.

Jeśli nie używasz BindingFlags.DoNotWrapExceptions funkcji podczas wywoływania Invoke()metody i masz catch instrukcje dotyczące Invoke() interfejsów API dla wyjątków innych niż TargetInvocationException, rozważ zmianę lub usunięcie tych catch instrukcji. Inne wyjątki nie będą już zgłaszane w wyniku wywołania. Jeśli jednak przechwytujesz wyjątki z weryfikacji argumentów, które mają miejsce przed podjęciem próby wywołania metody docelowej, należy zachować te catch instrukcje. Nieprawidłowe argumenty, które są weryfikowane przed podjęciem próby wywołania, są zgłaszane bez zawijania TargetInvocationException i nie zmieniły semantyki.

Rozważ użycie BindingFlags.DoNotWrapExceptions metody , aby TargetInvocationException nigdy nie zostało to rzucone. W takim przypadku wyjątek źródłowy nie zostanie opakowany przez element TargetInvocationException. W większości przypadków nie opakowywanie wyjątku zwiększa prawdopodobieństwo diagnozowania rzeczywistego problemu, ponieważ nie wszystkie narzędzia raportowania wyjątków wyświetlają wyjątek wewnętrzny. Ponadto przy użyciu metody BindingFlags.DoNotWrapExceptionszostaną zgłoszone te same wyjątki, co podczas bezpośredniego wywoływania metody (bez odbicia). Jest to pożądane w większości przypadków, ponieważ wybór, czy odbicie jest używane, czy nie może być dowolne lub szczegóły implementacji, które nie muszą być uwidocznione w obiekcie wywołującym.

W rzadkich przypadkach, gdy musisz przekazać wartość domyślną do metody poprzez odbicie zawierające parametr przypominający byref, który jest przekazywany "według wartości", można dodać metodę otoki, która pomija parametr i wywołuje metodę docelową z wartością domyślną dla tego parametru.

Dotyczy interfejsów API