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, którzy pierwotnie opracowali lub nadal opracowywali aplikacje .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 5 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ół platformy .NET zbliża się do możliwych zmian powodujących niezgodność, jest szczególnie przydatne dla deweloperów, którzy otwierają żądania ściągnięcia modyfikujące zachowanie istniejących interfejsów API platformy .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

  • Oprócz obsługi jako przewodnika po sposobie oceniania zmian bibliotek platformy .NET deweloperzy bibliotek mogą również użyć tych kryteriów do oceny zmian w bibliotekach przeznaczonych dla wielu implementacji i wersji platformy .NET.
  • Aby uzyskać informacje na temat kategorii zgodności, na przykład zgodności z poprzednimi wersjami i do przodu, zobacz 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ą one zgodność z poprzednimi wersjami (możliwość 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 poziomie obniżonym. Przykładem jest ISerializable interfejs.

  • WYMAGA OSĄDU: 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 DbConnection klasa stała się nową klasą bazową dla SqlConnectionprogramu , która wcześniej pochodziła bezpośrednio z Componentklasy .

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

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

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

    readonly struct Zmiana typu na struct typ 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

    Spowoduje to przerwanie wszystkich kodu, który używa zmienionego lub usuniętego typu.

    Uwaga

    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 . Zasady pomocy technicznej platformy .NET można znaleźć w temacie Zasady pomocy technicznej platformy .NET.

  • NIEDOZWOLONE: Zmiana bazowego typu wyliczenia

    Jest to zmiana powodująca niezgodność w czasie kompilacji i zachowanie, a także binarną zmianę powodującą niezgodność, która może sprawić, że argumenty atrybutów będą nierozłączelne.

  • NIEDOZWOLONE: Uszczelnianie typu, który był wcześniej niezauczętowany

  • 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 element , który implementuje IComponentIDisposableelement .

  • DISALLOWED: zmiana readonly struct typu na typ struktury

    Jednak zmiana struct typu na readonly struct typ jest dozwolona.

  • DISALLOWED: zmiana typu struktury na ref struct typ i odwrotnie

  • NIEDOZWOLONE: zmniejszenie widoczności typu

    Jednak zwiększenie widoczności typu jest dozwolone.

Elementy członkowskie

  • ✔️ DOZWOLONE: rozszerzanie widoczności elementu członkowskiego, 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 dodanie abstrakcyjnego elementu członkowskiego do typu, który ma dostępne (publiczne lub chronione) konstruktory i nie sealed jest dozwolony.

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

  • ✔️ DOZWOLONE: przeniesienie elementu członkowskiego do klasy wyższej w hierarchii niż typ, z którego został usunięty

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

    Wprowadzenie przesłonięcia może spowodować, że poprzedni użytkownicy przesłonią 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 abstrakcji na wirtualną

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

  • ✔️ DOZWOLONE: usuwanie odczytu z pola, chyba że statyczny typ pola jest modyfikowalnym typem wartości

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

  • WYMAGA OSĄDU: Dodawanie nowego pola wystąpienia do typu

    Ta zmiana ma wpływ na serializacji.

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

    Spowoduje to przerwanie wszystkich kodu, który używa zmienionej nazwy lub usuniętego elementu członkowskiego lub parametru.

    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.

  • NIEDOZWOLONE: Dodawanie elementu członkowskiego do interfejsu

    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ą domyślne elementy członkowskie interfejsu (DIM). Ponadto w niektórych scenariuszach środowisko uruchomieniowe nie może zdecydować, który domyślny element członkowski interfejsu ma być wywoływany. Z tych powodów dodanie elementu członkowskiego do istniejącego interfejsu jest uznawane za zmianę powodującą niezgodność.

  • DISALLOWED: Zmiana wartości elementu członkowskiego stałej publicznej lub 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 opóźnieniem, takie jak funkcja późnego powiązania w Visual Basic i dynamiczne w języku C#.

    • Przerywa zgodność źródła, gdy deweloperzy używają nazwanych argumentów.

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

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

  • NIEDOZWOLONE: Dodawanie lub usuwanie abstrakcji z elementu członkowskiego

  • DISALLOWED: Usuwanie wirtualnego słowa kluczowego z elementu członkowskiego

  • DISALLOWED: Dodawanie wirtualnego słowa kluczowego do elementu członkowskiego

    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 innych niż wirtualne (callvirt wykonuje sprawdzanie wartości null, podczas gdy normalne wywołanie nie jest), to zachowanie nie jest niezmienne 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 wywołanie normalne za każdym razem, 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 odbiorcy często wywołuje go niewirtualnie.

  • DISALLOWED: Tworzenie wirtualnego elementu członkowskiego abstrakcyjnego

    Wirtualny element członkowski udostępnia implementację metody, która może zostać 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 nie będzie to wirtualne, uniemożliwiając implementację tego elementu członkowskiego pochodnego.

  • 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 statycznego słowa kluczowego 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. Jeśli na przykład klasa ma jedną wersję metody, która akceptuje UInt32element , istniejący odbiorca zostanie pomyślnie powiązany z tym przeciążeniem podczas przekazywania Int32 wartości. Jeśli jednak dodasz przeciążenie, które akceptuje Int32element podczas ponownego kompilowania lub używania opóźnionego powiązania, kompilator wiąże się teraz z nowym przeciążeniem. Jeśli wyniki różnych zachowań, jest to zmiana powodująca niezgodność.

  • DISALLOWED: dodanie konstruktora do klasy, która wcześniej nie miała konstruktora bez dodawania konstruktora bez parametrów

  • ❌✔ NIEDOZWOLONE: dodawanie readonly do pola

  • NIEDOZWOLONE: Zmniejszenie widoczności elementu członkowskiego

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

    Zwiększenie widoczności elementu członkowskiego jest dozwolone.

  • NIEDOZWOLONE: zmiana typu elementu członkowskiego

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

  • DISALLOWED: Dodawanie pola wystąpienia do struktury, która nie ma pól niepublikowanych

    Jeśli struktura ma tylko pola publiczne lub w ogóle nie ma pól, wywołujące mogą deklarować lokalizacje lokalne tego typu struktury bez wywoływania konstruktora struktury lub pierwszego inicjowania lokalnego na default(T), tak długo, jak wszystkie pola publiczne są ustawione na strukturę przed pierwszym użyciem. Dodanie nowych pól — publicznych lub niepublikowanych — do takiej struktury jest zmianą powodującą niezgodność źródła dla tych obiektów wywołujących, ponieważ kompilator będzie teraz wymagać zainicjowania dodatkowych pól.

    Ponadto dodanie nowych pól — publicznych lub niepublikacyjnych — do struktury bez pól lub tylko pól publicznych jest binarną zmianą powodującą niezgodność w obiektach wywołujących, które zostały zastosowane [SkipLocalsInit] do ich kodu. Ponieważ kompilator nie wiedział o tych polach w czasie kompilacji, może emitować il, który nie w pełni inicjuje struktury, co prowadzi do utworzenia struktury na podstawie niezainicjowanych danych 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: Wypalanie istniejącego zdarzenia, gdy nigdy wcześniej nie zostało wyzwolone

Zmiany zachowań

Zestawy

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

  • NIEDOZWOLONE: zmiana nazwy zestawu

  • NIEDOZWOLONE: Zmiana klucza publicznego zestawu

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ć String wystąpienie. (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, nie można rozwinąć parametru lub typu składowego. 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 element członkowski jest wirtualny

    Ta zmiana powoduje przerwanie istniejących przesłonięć elementów członkowskich, które nie będą działać poprawnie dla rozszerzonego 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

  • DISALLOWED: zmiana zwracanych wartości dla właściwości, pola, wartości zwracanej 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 jest podziałem źródłowym, a zmiana wartości domyślnej parametru może spowodować przerwanie 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 z dwoma MyMethod opcjonalnymi parametrami a i b, można zachować zgodność, przenosząc wartość a domyślną do nowego przeciążenia. Teraz dwa przeciążenia to MyMethod(int a) i MyMethod(int a = 1, int b = 2). Ten wzorzec umożliwia MyMethod() skompilowanie.

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

  • WYMAGA WYROKU: Zmiana analizy danych wejściowych i zgłaszania nowych wyjątków (nawet jeśli zachowanie analizy 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 kultury i pobierania zaczęły zgłaszać wartość CultureNotFoundException zamiast ArgumentException , jeśli nie można odnaleźć kultury. Ponieważ CultureNotFoundException pochodzi z ArgumentExceptionmetody , 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

    Nie należy przechwytywać nieodwracalnych wyjątków, ale zamiast tego powinny być obsługiwane przez procedurę obsługi typu catch-all 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 rzuciła ArgumentOutOfRangeException inaczej, można zmienić 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ść.

Obsługa platform

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

  • NIEDOZWOLONE: Brak obsługi lub teraz 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ż przerywają prywatne odbicie. 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 WYROKU: Zmiana wewnętrznej implementacji elementu członkowskiego

    Te zmiany są ogólnie dozwolone, chociaż przerywają prywatne odbicie. 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 zachowanie danego interfejsu API; w przeciwnym razie zmiana będzie przerywana.

  • ✔️ DOZWOLONE: Pośrednio (i często niekorzystnie) zmiana wydajności operacji

    Jeśli zmiana, o których mowa, nie jest kategoryzowana jako niezgodna z jakiegoś 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 interfejsu API na asynchroniczną (i odwrotnie)

Zmiany kodu

  • ✔️ DOZWOLONE: dodawanie parametrów do parametru

  • DISALLOWED: Zmiana struktury na klasę i odwrotnie

  • DISALLOWED: Dodawanie zaznaczonego słowa kluczowego do bloku kodu

    Ta zmiana może spowodować, że kod, który został wcześniej wykonany w celu wyrzucenia elementu OverflowException i jest niedopuszczalny.

  • DISALLOWED: Usuwanie parametrów z parametru

  • NIEDOZWOLONE: zmiana kolejności wyzwalania zdarzeń

    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 wywołań podanych zdarzeń

  • DISALLOWED: dodawanie elementu FlagsAttribute do typu wyliczenia

Zobacz też