Udostępnij przez


Zmienianie reguł zgodności

W całej historii platforma .NET próbowała zachować wysoki poziom zgodności z wersji na wersję i we wszystkich implementacjach platformy .NET. Mimo że platformy .NET 5 (i .NET Core) i nowsze wersje można traktować jako nową technologię w porównaniu z programem .NET Framework, dwa główne czynniki ograniczają możliwość tej implementacji platformy .NET, aby odbiegać od platformy .NET Framework:

  • Duża liczba deweloperów pierwotnie zajmowała się opracowaniem lub nadal zajmuje się opracowywaniem aplikacji .NET Framework. Oczekują one spójnego zachowania w implementacjach platformy .NET.
  • Projekty bibliotek platformy .NET Standard umożliwiają deweloperom tworzenie bibliotek przeznaczonych dla typowych interfejsów API udostępnianych przez programy .NET Framework i .NET 5 (i .NET Core) oraz nowsze wersje. Deweloperzy oczekują, że biblioteka używana w aplikacji .NET powinna zachowywać się identycznie z tą samą biblioteką używaną w aplikacji .NET Framework.

Oprócz zgodności w implementacjach platformy .NET deweloperzy oczekują wysokiego poziomu zgodności w różnych wersjach danej implementacji platformy .NET. W szczególności kod napisany dla starszej wersji platformy .NET Core powinien działać bezproblemowo na platformie .NET 5 lub nowszej wersji. W rzeczywistości wielu deweloperów oczekuje, że nowe interfejsy API znalezione w nowo wydanych wersjach platformy .NET powinny być również zgodne z wersjami wstępnymi, w których wprowadzono te interfejsy API.

W tym artykule opisano zmiany wpływające na zgodność i sposób, w jaki zespół platformy .NET ocenia każdy typ zmiany. Zrozumienie, w jaki sposób zespół .NET podchodzi do możliwych zmian powodujących niezgodność, jest szczególnie przydatne dla deweloperów, którzy otwierają pull requesty modyfikujące zachowanie istniejących API .NET.

W poniższych sekcjach opisano kategorie zmian wprowadzonych w interfejsach API platformy .NET oraz ich wpływ na zgodność aplikacji. Zmiany są dozwolone (), niedozwolone (✔️❌) lub wymagają osądu oraz oceny, jak przewidywalne, oczywiste i spójne było poprzednie zachowanie (❓).

Uwaga / Notatka

  • Oprócz pełnienia funkcji przewodnika po ocenie zmian w bibliotekach .NET, twórcy bibliotek mogą również wykorzystać te kryteria do oceny zmian w swoich bibliotekach przeznaczonych dla różnych implementacji i wersji platformy .NET.
  • Aby uzyskać informacje na temat kategorii zgodności, na przykład zgodności wstecznej i zgodności z przyszłymi wersjami, zobacz w Jak zmiany kodu mogą mieć wpływ na zgodność.

Modyfikacje umowy publicznej

Zmiany w tej kategorii modyfikują obszar powierzchni publicznej typu. Większość zmian w tej kategorii jest niedozwolona, ponieważ naruszają zgodność wsteczną (zdolność aplikacji opracowanej przy użyciu poprzedniej wersji interfejsu API do wykonania bez ponownej kompilacji, w nowszej wersji).

Typy

  • ✔️ DOZWOLONE: Usuwanie implementacji interfejsu z typu, gdy interfejs jest już implementowany przez typ podstawowy

  • WYMAGA OSĄDU: Dodawanie nowej implementacji interfejsu do typu

    Jest to akceptowalna zmiana, ponieważ nie ma ona negatywnego wpływu na istniejących klientów. Wszelkie zmiany typu muszą działać w granicach dopuszczalnych zmian zdefiniowanych tutaj, aby nowa implementacja pozostała akceptowalna. Skrajna ostrożność jest niezbędna w przypadku dodawania interfejsów, które bezpośrednio wpływają na zdolność projektanta lub serializatora do generowania kodu lub danych, których nie można używać na niższym poziomie. Przykładem jest ISerializable interfejs.

  • WYMAGA ZASTANOWIENIA: Wprowadzenie nowej klasy bazowej

    Typ można wprowadzić do hierarchii między dwoma istniejącymi typami, jeśli nie wprowadza żadnych nowych abstrakcyjnych elementów członkowskich lub zmienia semantyka lub zachowanie istniejących typów. Na przykład w programie .NET Framework 2.0 klasa DbConnection stała się nową klasą bazową dla SqlConnection programu, który wcześniej dziedziczył bezpośrednio z klasy Component.

  • ✔️ DOZWOLONE: Przenoszenie typu z jednego zestawu do innego

    Stary zestaw musi być oznaczony elementem TypeForwardedToAttribute wskazującym nowy zestaw.

  • ✔️ DOZWOLONE: zmiana typu struct na readonly struct typ

    Zmiana z typu readonly struct na typ struct jest niedozwolona.

  • ✔️ DOZWOLONE: dodawanie zapieczętowanego lub abstrakcyjnego słowa kluczowego do typu, gdy nie ma dostępnych (publicznych lub chronionych) konstruktorów

  • ✔️ DOZWOLONE: rozszerzanie widoczności typu

  • NIEDOZWOLONE: zmiana przestrzeni nazw lub nazwy typu

  • NIEDOZWOLONE: zmiana nazwy lub usunięcie typu publicznego

    To spowoduje, że cały kod, który używa przemianowanego lub usuniętego typu, przestanie działać.

    Uwaga / Notatka

    W rzadkich przypadkach platforma .NET może usunąć publiczny interfejs API. Aby uzyskać więcej informacji, zobacz Usuwanie interfejsu API na platformie .NET. Aby uzyskać informacje o zasadach wsparcia dla platformy .NET, zobacz Zasady pomocy technicznej platformy .NET.

  • NIEDOZWOLONE: Zmiana bazowego typu wyliczenia

    Jest to zmiana powodująca niezgodność w czasie kompilacji oraz w zachowaniu, a także binarną zmianę powodującą niezgodność, która może sprawić, że argumenty atrybutów będą nierozpoznawalne.

  • NIEDOZWOLONE: Zamykanie typu, który wcześniej nie był zamknięty

  • NIEDOZWOLONE: Dodawanie interfejsu do zestawu podstawowych typów interfejsu

    Jeśli interfejs implementuje interfejs, który wcześniej nie zaimplementował, wszystkie typy implementujące oryginalną wersję interfejsu są uszkodzone.

  • WYMAGA OSĄDU: Usunięcie klasy z zestawu klas bazowych lub interfejsu z zestawu zaimplementowanych interfejsów

    Istnieje jeden wyjątek od reguły usuwania interfejsu: można dodać implementację interfejsu pochodzącego z usuniętego interfejsu. Na przykład można usunąć IDisposable, jeśli typ lub interfejs implementuje teraz IComponent, który implementuje IDisposable.

  • DISALLOWED: zmiana readonly struct typu na typ struktury

    Jednak zmiana struct typu na readonly struct typ jest dozwolona.

  • NIEDOZWOLONE: zmiana typu struct na typ ref struct i odwrotnie

  • NIEDOZWOLONE: zmniejszenie widoczności typu

    Jednak zwiększenie widoczności typu jest dozwolone.

Członkowie

  • ✔️ DOZWOLONE: rozszerzanie widoczności członka, który nie jest wirtualny

  • ✔️ DOZWOLONE: dodawanie abstrakcyjnego elementu członkowskiego do typu publicznego, który nie ma dostępnych (publicznych lub chronionych) konstruktorów lub typ jest zapieczętowany

    Jednak dodawanie abstrakcyjnego elementu członkowskiego do typu, który posiada dostępne (publiczne lub chronione) konstruktory i nie jest sealed, nie jest dozwolone.

  • ✔️ DOZWOLONE: Ograniczanie widoczności chronionego elementu członkowskiego, gdy typ nie ma dostępnych (publicznych lub chronionych) konstruktorów lub gdy typ jest zamknięty

  • ✔️ DOZWOLONE: przeniesienie członka do klasy wyższej w hierarchii niż typ, z którego pochodzi

  • ✔️ DOZWOLONE: dodawanie lub usuwanie przesłonięcia

    Wprowadzenie przesłonięcia może spowodować, że poprzedni konsumenci pominą przesłonięcie podczas wywoływania bazy.

  • ✔️ DOZWOLONE: Dodanie konstruktora do klasy wraz z konstruktorem bez parametrów, jeśli klasa wcześniej nie miała konstruktorów

    Jednak dodanie konstruktora do klasy, która wcześniej nie miała konstruktorów bez dodawania konstruktora bez parametrów, jest niedozwolone.

  • ✔️ DOZWOLONE: zmiana elementu członkowskiego z abstrakcyjnego na wirtualny

  • ✔️ DOZWOLONE: zmiana wartości zwracanej z ref readonly na ref (z wyjątkiem metod wirtualnych lub interfejsów)

  • ✔️ DOZWOLONE: usuwanie readonly z pola, z wyjątkiem sytuacji, gdy statycznym typem tego pola jest zmienialny typ wartości

  • ✔️ DOZWOLONE: wywoływanie nowego zdarzenia, które nie zostało wcześniej zdefiniowane

  • WYMAGA ROZWAŻENIA: Dodawanie nowego pola obiektowego do typu

    Ta zmiana ma wpływ na serializację.

  • NIEDOZWOLONE: zmiana nazwy lub usunięcie publicznego członka lub parametru

    Spowoduje to przerwanie całego kodu, który używa elementu lub parametru, do którego zmieniono nazwę lub który został usunięty.

    Obejmuje to usuwanie lub zmienianie nazwy elementu pobierającego lub ustawiającego z właściwości, a także zmienianie nazw lub usuwanie elementów członkowskich wyliczenia.

  • WYMAGANA ROZWAGA: Dodawanie członka do interfejsu

    Chociaż jest to zmiana powodująca niezgodność w tym sensie, że podnosi minimalną wersję platformy .NET do platformy .NET Core 3.0 (C# 8.0), co oznacza, że domyślne elementy członkowskie interfejsu (DIM) zostały wprowadzone, dodanie statycznego, nie abstrakcyjnego, niewirtualnego elementu członkowskiego do interfejsu jest dozwolone.

    Jeśli podasz implementację, dodanie nowego elementu członkowskiego do istniejącego interfejsu niekoniecznie spowoduje błędy kompilacji w zestawach podrzędnych. Jednak nie wszystkie języki obsługują narzędzia DIM. Ponadto w niektórych scenariuszach środowisko uruchomieniowe nie może zdecydować, który domyślny element członkowski interfejsu ma być wywoływany. W niektórych scenariuszach interfejsy są implementowane przez typy ref struct. Typów ref struct nie można boksować, więc nie mogą być konwertowane na typy interfejsów. Typy muszą zapewnić implikowaną implementację dla każdego elementu interfejsu. Nie mogą korzystać z domyślnej implementacji udostępnionej przez interfejs. Z tych powodów należy wykorzystać osąd przy dodawaniu członka do istniejącego interfejsu.

  • DISALLOWED: Zmiana wartości stałej publicznej lub członka wyliczenia

  • NIEDOZWOLONE: Zmiana typu właściwości, pola, parametru lub wartości zwracanej

  • NIEDOZWOLONE: Dodawanie, usuwanie lub zmienianie kolejności parametrów

  • NIEDOZWOLONE: Dodawanie lub usuwanie słowa kluczowego in, out lub ref z parametru

  • DISALLOWED: zmiana nazwy parametru (w tym zmiana wielkości liter)

    Jest to uznawane za niezgodność z dwóch powodów:

    • Przerywa ona scenariusze związane z późnym wiązaniem, takie jak funkcja późnego powiązania w Visual Basic i dynamic w języku C#.

    • Deweloperzy tracą zgodność ze źródłem, gdy używają nazwanych argumentów.

  • DISALLOWED: Zmiana wartości zwracanej ref na wartość zwracaną ref readonly

  • ❌✔ NIEDOZWOLONE: Zmiana wartości zwracanej z ref readonly na ref w metodzie wirtualnej lub interfejsie

  • NIEDOZWOLONE: Dodawanie lub usuwanie abstract z członka

  • DISALLOWED: Usuwanie wirtualnego słowa kluczowego z członka

  • DISALLOWED: Dodawanie virtualnego słowa kluczowego do członka

    Chociaż często nie jest to zmiana powodująca niezgodność, ponieważ kompilator języka C# ma tendencję do emitowania instrukcji callvirt Intermediate Language (IL) w celu wywołania metod niewirtualnych (callvirt wykonuje sprawdzanie wartości null, podczas gdy normalne wywołanie nie jest), to zachowanie może być zmienne z kilku powodów:

    • Język C# nie jest jedynym językiem przeznaczonym dla platformy .NET.
    • Kompilator języka C# coraz częściej próbuje zoptymalizować callvirt do normalnego wywołania w sytuacji, gdy metoda docelowa nie jest wirtualna i prawdopodobnie nie ma wartości null (np. metody dostępnej za pośrednictwem operatora propagacji wartości null ?).

    Utworzenie metody wirtualnej oznacza, że kod klienta często wywołuje ją nie w sposób wirtualny.

  • DISALLOWED: Tworzenie wirtualnego członka abstrakcyjnego

    Wirtualny członek udostępnia implementację metody, która może być zastąpiona przez klasę pochodną. Abstrakcyjny element członkowski nie zapewnia implementacji i musi zostać zastąpiony.

  • NIEDOZWOLONE: Dodawanie zapieczętowanego słowa kluczowego do elementu członkowskiego interfejsu

    Dodanie sealed do domyślnego elementu członkowskiego interfejsu spowoduje, że stanie się niewirtualne, uniemożliwiając wywołanie implementacji tego elementu członkowskiego przez typ pochodny.

  • NIEDOZWOLONE: dodawanie abstrakcyjnego elementu członkowskiego do typu publicznego, który ma dostępne (publiczne lub chronione) konstruktory i które nie są zapieczętowane

  • NIEDOZWOLONE: Dodawanie lub usuwanie słowa kluczowego static z elementu członkowskiego

  • NIEDOZWOLONE: Dodawanie przeciążenia, które wyklucza istniejące przeciążenie i definiuje inne zachowanie

    Spowoduje to przerwanie istniejących klientów powiązanych z poprzednim przeciążeniem. Na przykład, jeśli klasa ma jedną wersję metody, która akceptuje UInt32, istniejący odbiorca zostanie pomyślnie powiązany z tym przeciążeniem podczas przekazywania wartości Int32. Jednak jeśli dodasz przeciążenie, które akceptuje element Int32, podczas ponownego kompilowania lub używania opóźnionego powiązania kompilator teraz wiąże się z nowym przeciążeniem. Jeśli skutkiem jest inne zachowanie, jest to zmiana łamiąca zgodność.

  • DISALLOWED: Dodanie konstruktora do klasy, która wcześniej go nie miała, bez dodania konstruktora bezparametrowego

  • ❌✔ NIEDOZWOLONE: dodawanie readonly do pola

  • NIEDOZWOLONE: Zmniejszenie widoczności członka

    Obejmuje to zmniejszenie widoczności chronionego elementu członkowskiego, gdy są dostępne konstruktory (public lub protected) i typ nie jest zapieczętowany. Jeśli tak nie jest, ograniczenie widoczności chronionego elementu jest dozwolone.

    Zwiększenie widoczności członka jest dozwolone.

  • NIEDOZWOLONE: zmiana typu członka

    Nie można zmodyfikować wartości zwracanej metody lub typu właściwości lub pola. Na przykład sygnatura metody zwracającej Object nie może zostać zmieniona w celu zwrócenia String wartości lub odwrotnie.

  • NIEDOZWOLONE: Dodawanie pola instancji do struktury, która nie ma pól prywatnych

    Jeśli struktura ma tylko pola publiczne lub w ogóle nie ma pól, można zadeklarować zmienne lokalne tego typu struktury bez wywoływania konstruktora struktury lub uprzedniej inicjalizacji zmiennej lokalnej na default(T), pod warunkiem że wszystkie pola publiczne są ustawione w strukturze przed pierwszym użyciem. Dodanie nowych pól — publicznych lub niepublicznych — do takiej struktury jest zmianą powodującą niezgodność w kodzie źródłowym dla tych wywołań, ponieważ kompilator będzie teraz wymagał zainicjowania dodatkowych pól.

    Ponadto dodanie nowych pól — publicznych lub niepublicznych — do struktury bez pól lub tylko pól publicznych stanowi binarną zmianę powodującą niezgodność dla obiektów wywołujących, które zaimplementowały [SkipLocalsInit] w swoim kodzie. Ponieważ kompilator nie wiedział o tych polach w czasie kompilacji, może emitować IL, który nie w pełni inicjalizuje strukturę, prowadząc do jej utworzenia na podstawie niezainicjowanych danych ze stosu.

    Jeśli struktura ma jakiekolwiek pola niepubliczne, kompilator wymusza już inicjowanie za pomocą konstruktora lub default(T), a dodanie nowych pól wystąpienia nie jest zmianą powodującą niezgodność.

  • NIEDOZWOLONE: Wywoływanie istniejącego zdarzenia, gdy nigdy wcześniej nie zostało uruchomione

Zmiany zachowania

Zgromadzenia

  • ✔️ DOZWOLONE: tworzenie przenośnego zestawu, gdy te same platformy są nadal obsługiwane

  • NIEDOZWOLONE: zmiana nazwy zestawu

  • NIEDOZWOLONE: Zmiana klucza publicznego zespołu

Właściwości, pola, parametry i wartości zwracane

  • ✔️ DOZWOLONE: zmiana wartości właściwości, pola, wartości zwracanej lub parametru na bardziej pochodny typ

    Na przykład metoda zwracająca typ Object może zwrócić egzemplarz String. (Jednak sygnatura metody nie może ulec zmianie).

  • ✔️ DOZWOLONE: Zwiększenie zakresu akceptowanych wartości dla właściwości lub parametru, jeśli element członkowski nie jest wirtualny

    Chociaż zakres wartości, które można przekazać do metody lub są zwracane przez element członkowski, może się rozwinąć, typ parametru lub elementu członkowskiego nie może. Na przykład, gdy wartości przekazane do metody mogą rozwinąć się z zakresu od 0 do 124 do 0–255, typ parametru nie może zmienić się z Byte na Int32.

  • DISALLOWED: Zwiększenie zakresu akceptowanych wartości dla właściwości lub parametru, jeśli członek jest wirtualny

    Ta zmiana zakłóca istniejące przesłonięte członki, które przestaną działać poprawnie dla szerszego zakresu wartości.

  • NIEDOZWOLONE: Zmniejszanie zakresu akceptowanych wartości dla właściwości lub parametru

  • NIEDOZWOLONE: Zwiększanie zakresu zwracanych wartości dla właściwości, pola, wartości zwracanej lub parametru out

  • Zakazane: zmiana zwracanych wartości dla właściwości, pola, zwracanej wartości metody lub parametru out

  • NIEDOZWOLONE: zmiana domyślnej wartości właściwości, pola lub parametru

    Zmiana lub usunięcie wartości domyślnej parametru nie jest podziałem binarnym. Usunięcie wartości domyślnej parametru może spowodować przerwanie zgodności z kodem źródłowym, a zmiana wartości domyślnej parametru może prowadzić do zmiany zachowania po ponownym skompilowaniu.

    Z tego powodu usunięcie wartości domyślnych parametrów jest dopuszczalne w konkretnym przypadku "przenoszenia" tych wartości domyślnych do nowego przeciążenia metody w celu wyeliminowania niejednoznaczności. Rozważmy na przykład istniejącą metodę MyMethod(int a = 1). Jeśli wprowadzisz przeciążenie MyMethod z dwoma opcjonalnymi parametrami a i b, można zachować zgodność, przenosząc domyślną wartość a do nowego przeciążenia. Teraz dwa przeciążenia to MyMethod(int a) oraz MyMethod(int a = 1, int b = 2). Ten wzorzec umożliwia skompilowanie MyMethod().

  • NIEDOZWOLONE: Zmiana dokładności wartości zwracanej liczbowej

  • WYMAGA ROZWAŻENIA: Zmiana parsowania danych wejściowych i zgłaszanie nowych wyjątków (nawet jeśli zachowanie parsowania nie jest określone w dokumentacji)

Wyjątki

  • ✔️ DOZWOLONE: zgłaszanie wyjątku pochodnego niż istniejący wyjątek

    Ponieważ nowy wyjątek jest podklasą istniejącego wyjątku, poprzedni kod obsługi wyjątków nadal obsługuje wyjątek. Na przykład w programie .NET Framework 4 metody tworzenia i pobierania ustawień regionalnych zaczęły zgłaszać wyjątek CultureNotFoundException zamiast ArgumentException , jeśli nie można odnaleźć ustawień regionalnych. Ponieważ CultureNotFoundException pochodzi z ArgumentException, jest to akceptowalna zmiana.

  • ✔️ DOZWOLONE: zgłaszanie bardziej szczegółowego wyjątku niż NotSupportedException, , NotImplementedExceptionNullReferenceException

  • ✔️ DOZWOLONE: zgłaszanie wyjątku, który jest uznawany za nieodwracalny

    Nieodwracalne wyjątki nie powinny być przechwytywane, lecz obsługiwanie ich powinno odbywać się przez ogólną procedurę obsługi wysokiego poziomu. W związku z tym użytkownicy nie powinni mieć kodu, który przechwytuje te jawne wyjątki. Nieodwracalne wyjątki to:

  • ✔️ DOZWOLONE: zgłaszanie nowego wyjątku w nowej ścieżce kodu

    Wyjątek musi dotyczyć tylko nowej ścieżki kodu, która jest wykonywana z nowymi wartościami parametrów lub stanami i których nie można wykonać za pomocą istniejącego kodu, który jest przeznaczony dla poprzedniej wersji.

  • ✔️ DOZWOLONE: Usuwanie wyjątku w celu włączenia bardziej niezawodnego zachowania lub nowych scenariuszy

    Na przykład metoda Divide, która wcześniej obsługiwała tylko wartości dodatnie i w przeciwnym razie wyrzucała wyjątek ArgumentOutOfRangeException, może być zmieniona tak, aby obsługiwała zarówno wartości ujemne, jak i dodatnie bez zgłaszania wyjątku.

  • ✔️ DOZWOLONE: zmiana tekstu komunikatu o błędzie

    Deweloperzy nie powinni polegać na tekście komunikatów o błędach, które również zmieniają się w oparciu o kulturę użytkownika.

  • NIEDOZWOLONE: Zgłaszanie wyjątku w każdym innym przypadku, który nie został wymieniony powyżej

  • NIEDOZWOLONE: Usuwanie wyjątku w każdym innym przypadku, który nie został wymieniony powyżej

Atrybuty

  • ✔️ DOZWOLONE: zmiana wartości atrybutu, który nie jest zauważalny

  • NIEDOZWOLONE: Zmiana wartości atrybutu, który można zaobserwować

  • WYMAGA OSĄDU: Usuwanie atrybutu

    W większości przypadków usunięcie atrybutu (takiego jak NonSerializedAttribute) jest zmianą powodującą niezgodność.

Wsparcie platform

  • ✔️ DOZWOLONE: obsługa operacji na platformie, która wcześniej nie była obsługiwana

  • NIEDOZWOLONE: Nieobsługiwanie lub obecnie wymaganie określonego dodatku Service Pack dla operacji, która była wcześniej obsługiwana na platformie

Zmiany implementacji wewnętrznej

  • WYMAGA OSĄDU: Zmiana obszaru powierzchni typu wewnętrznego

    Takie zmiany są ogólnie dozwolone, chociaż zakłócają prywatną refleksję. W niektórych przypadkach, gdy popularne biblioteki innych firm lub duża liczba deweloperów zależą od wewnętrznych interfejsów API, takie zmiany mogą nie być dozwolone.

  • WYMAGA OCENY: Zmiana wewnętrznej implementacji elementu

    Te zmiany są zazwyczaj dozwolone, nawet jeśli naruszają prywatne mechanizmy refleksji. W niektórych przypadkach, gdy kod klienta często zależy od odbicia prywatnego lub gdy zmiana wprowadza niezamierzone skutki uboczne, te zmiany mogą nie być dozwolone.

  • ✔️ DOZWOLONE: Poprawianie wydajności operacji

    Możliwość modyfikowania wydajności operacji jest niezbędna, ale takie zmiany mogą przerwać kod, który opiera się na bieżącej szybkości operacji. Dotyczy to szczególnie kodu, który zależy od chronometrażu operacji asynchronicznych. Zmiana wydajności nie powinna mieć wpływu na inne aspekty działania danego interfejsu API; w przeciwnym razie zmiana będzie naruszać kompatybilność.

  • ✔️ DOZWOLONE: Pośrednio (i często niekorzystnie) zmieniając wydajność operacji

    Jeśli zmiana, o której mowa, nie jest kategoryzowana jako przełomowa z innego powodu, jest to dopuszczalne. Często należy podjąć działania, które mogą obejmować dodatkowe operacje lub dodać nowe funkcje. Będzie to prawie zawsze miało wpływ na wydajność, ale może być niezbędne, aby interfejs API, o której mowa, działał zgodnie z oczekiwaniami.

  • DISALLOWED: zmiana synchronicznego API na asynchroniczny (i odwrotnie)

Zmiany kodu

  • ✔️ DOZWOLONE: dodawanie parametrów do parametru

  • NIEDOZWOLONE: Zmiana struktury na klasę i odwrotnie

  • DISALLOWED: Dodawanie instrukcji checked do bloku kodu

    Ta zmiana może spowodować, że kod, który wcześniej działał poprawnie, zacznie generować OverflowException, co jest niedopuszczalne.

  • NIEDOZWOLONE: Usuwanie params z parametrów

  • NIEDOZWOLONE: zmiana kolejności, w jakiej zdarzenia są wyzwalane

    Deweloperzy mogą rozsądnie oczekiwać, że zdarzenia będą uruchamiane w tej samej kolejności, a kod dewelopera często zależy od kolejności uruchamiania zdarzeń.

  • NIEDOZWOLONE: Usuwanie wywoływanego zdarzenia w danej akcji

  • NIEDOZWOLONE: zmiana liczby razy, gdy podane zdarzenia są wywoływane

  • DISALLOWED: dodawanie elementu FlagsAttribute do typu wyliczenia

Zobacz także