Změna pravidel pro zajištění kompatibility

V průběhu své historie se .NET pokusil zachovat vysokou úroveň kompatibility od verze po verzi a napříč implementacemi .NET. I když .NET 5 (a .NET Core) a novější verze lze považovat za novou technologii v porovnání s .NET Frameworkem, dvě hlavní faktory omezují schopnost této implementace .NET se od rozhraní .NET Framework lišit:

  • Velký počet vývojářů, kteří původně vyvinuli nebo pokračovali ve vývoji aplikací .NET Framework. Očekávají konzistentní chování napříč implementacemi .NET.
  • .NET projekty standardní knihovny umožňují vývojářům vytvářet knihovny, které cílí na běžná rozhraní API sdílená rozhraním .NET Framework a .NET 5 (a .NET Core) a novější verze. Vývojáři očekávají, že knihovna používaná v aplikaci .NET by se měla chovat stejně jako stejná knihovna používaná v aplikaci .NET Framework.

Spolu s kompatibilitou napříč implementacemi .NET očekávají vývojáři vysokou úroveň kompatibility napříč verzemi dané implementace .NET. Kód napsaný pro starší verzi .NET Core by měl běžet bezproblémově na .NET 5 nebo novější verzi. Ve skutečnosti mnoho vývojářů očekává, že nová rozhraní API nalezená v nově vydaných verzích .NET by také měla být kompatibilní s předběžnými verzemi, ve kterých byla tato rozhraní API zavedena.

Tento článek popisuje změny, které ovlivňují kompatibilitu a způsob, jakým tým .NET vyhodnocuje jednotlivé typy změn. Pochopení toho, jak .NET tým přistupuje k možným zásadním změnám, je užitečný zejména pro vývojáře, kteří otevírají žádosti o přijetí změn, které upravují chování stávajících rozhraní API .NET.

Následující části popisují kategorie změn provedených v rozhraních API .NET a jejich dopad na kompatibilitu aplikací. Změny jsou buď povolené (), nepovolené (✔️❌), nebo vyžadují úsudek a vyhodnocení toho, jak předvídatelné, zřejmé a konzistentní bylo předchozí chování (❓).

Poznámka:

  • Kromě toho, že slouží jako vodítko, jak se vyhodnocují změny .NET knihoven, mohou vývojáři knihoven tato kritéria použít také k vyhodnocení změn knihoven, které cílí na více .NET implementací a verzí.
  • Informace o kategoriích kompatibility, například dopředné a zpětné kompatibility, naleznete v tématu Jak můžou změny kódu ovlivnit kompatibilitu.

Úpravy veřejné zakázky

Změny v této kategorii upravují veřejnou plochu typu. Většina změn v této kategorii je zakázána, protože porušují zpětnou kompatibilitu (schopnost aplikace vyvinuté s předchozí verzí rozhraní API ke spuštění bez rekompilace u novější verze).

Typy

  • ✔️ POVOLENO: Odebrání implementace rozhraní z typu, pokud rozhraní je již implementováno základním typem

  • VYŽADUJE ÚSUDEK: Přidání nové implementace rozhraní do typu

    Jedná se o přijatelnou změnu, protože nemá nepříznivý vliv na stávající klienty. Všechny změny typu musí fungovat v rámci hranic přijatelných změn definovaných zde, aby nová implementace zůstala přijatelná. Je extrémně důležité být opatrný při přidávání rozhraní, která přímo ovlivňují schopnosti návrháře nebo serializátoru generovat kód nebo data, jež nelze využívat na nižších úrovních. Příkladem je ISerializable rozhraní.

  • VYŽADUJE ÚSUDEK: Představujeme novou základní třídu.

    Typ lze zavést do hierarchie mezi dvěma existujícími typy, pokud nezavádějí žádné nové abstraktní členy nebo nemění sémantiku nebo chování existujících typů. Například v .NET Framework 2.0 se třída DbConnection stala novou základní třídou pro SqlConnection, která byla dříve odvozena přímo z Component.

  • ✔️ POVOLENO: Přesunutí typu z jednoho sestavení do druhého

    Staré sestavení musí být označeno odkazem TypeForwardedToAttribute na nové sestavení.

  • ✔️ POVOLENO: Změna typu struktury na readonly struct typ

    readonly struct Změna typu na struct typ není povolená.

  • ✔️ POVOLENO: Přidání zapečetěného nebo abstraktního klíčového slova do typu, pokud nejsou k dispozici žádné přístupné (veřejné nebo chráněné) konstruktory

  • ✔️ POVOLENO: Rozšíření viditelnosti typu

  • NEDOVOLENO: Změnit obor názvů nebo název typu

  • ZAKÁZÁNO: Veřejný typ nelze přejmenovat nebo odebrat

    Tím se přeruší veškerý kód, který používá přejmenovaný nebo odebraný typ.

    Poznámka:

    Ve výjimečných případech může .NET odebrat veřejné rozhraní API. Další informace najdete v tématu o odebrání API v .NET. Informace o zásadách podpory .NET najdete v tématu .NET Zásady podpory.

  • DISALLOWED: Změna základního typu výčtu

    Jedná se o změnu, která způsobuje chyby při kompilaci, narušuje běh programu a mění binární kompatibilitu, což může způsobit, že argumenty atributů budou neinterpretovatelné.

  • ZAKÁZÁNO: Zapečetění typu, který byl dříve nezapečetěn

  • DISALLOWED: Přidání rozhraní do sady základních typů rozhraní

    Pokud rozhraní začne implementovat jiné rozhraní, které dříve neimplementovalo, všechny typy, které původní verzi rozhraní implementovaly, se rozbijí.

  • VYŽADUJE ÚSUDEK: Odebrání třídy ze sady základních tříd nebo rozhraní ze sady implementovaných rozhraní

    Existuje jedna výjimka pravidla pro odebrání rozhraní: můžete přidat implementaci rozhraní, které je odvozeno z odebraného rozhraní. Můžete například odebrat IDisposable , pokud typ nebo rozhraní nyní implementuje IComponent, který implementuje IDisposable.

  • DISALLOWED: Změna readonly struct typu na typ struct

    Změna typu struct na typ readonly struct je však povolená.

  • NEPOVOLENO: Změna typu struct na typ ref struct, a naopak

  • ZAKÁZÁNO: Snížení viditelnosti typu

    Zvýšení viditelnosti typu je však povoleno.

Členové

  • ✔️ POVOLENO: Rozšíření viditelnosti člena, který není virtuální

  • ✔️ POVOLENO: Přidání abstraktního členu do veřejného typu, který nemá přístupné (veřejné nebo chráněné) konstruktory nebo je typ zapečetěn

    Přidání abstraktního členu do typu, který má přístupné (veřejné nebo chráněné) konstruktory, není sealed povoleno.

  • ✔️ POVOLENO: Omezení viditelnosti chráněného členu, pokud typ nemá přístupné (veřejné nebo chráněné) konstruktory nebo je typ zapečetěn.

  • ✔️ POVOLENO: Přesunutí člena do vyšší třídy v hierarchii než typ, ze kterého byl odebrán

  • ✔️ POVOLENO: Přidání nebo odebrání přepsání

    Zavedení přepsání může způsobit, že předchozí příjemci přeskočili přepsání při volání základu.

  • ✔️ POVOLENO: Přidání konstruktoru do třídy spolu s konstruktorem bez parametrů, pokud třída dříve neměla žádné konstruktory

    Přidání konstruktoru do třídy, která dříve žádné konstruktory neměla, bez přidání konstruktoru bez parametrů, není dovoleno.

  • ✔️ POVOLENO: Změna člena z abstraktního na virtuální

  • ✔️ POVOLENO: Změna z ref readonly hodnoty na návratovou ref hodnotu (s výjimkou virtuálních metod nebo rozhraní)

  • ✔️ POVOLENO: Odebrání atributu readonly z pole, pokud statický typ pole není typem s měnitelnou hodnotou

  • ✔️ POVOLENO: Volání nové události, která nebyla dříve definována

  • VYŽADUJE ROZSUDEK: Přidání nového pole instance do typu

    Tato změna má vliv na serializaci.

  • DISALLOWED: Přejmenování nebo odebrání veřejného člena nebo parametru

    Tím se přeruší veškerý kód, který používá přejmenovaný nebo odebraný člen nebo parametr.

    To zahrnuje odebrání nebo přejmenování getteru nebo setter z vlastnosti a také přejmenování nebo odebrání členů výčtu.

  • VYŽADUJE ÚSUDEK: Přidání člena do rozhraní

    I když se jedná o zásadní změnu v tom smyslu, že zvyšuje minimální verzi .NET na .NET Core 3.0 (C# 8.0), což je verze, kdy byly zavedeny default interface members (DIM), je povoleno přidat statického, neabstraktního, nevirtuálního člena do rozhraní.

    Pokud zadáte implementaci, přidání nového člena do existujícího rozhraní nemusí nutně způsobit selhání kompilace v následných sestaveních. Ne všechny jazyky však podporují dimy. V některých scénářích se modul runtime také nemůže rozhodnout, který výchozí člen rozhraní se má vyvolat. Počínaje C# 13 mohou typy implementovat rozhraní, ale nemohou být zabaleny ani převedeny na typ rozhraní. ref struct Proto musí typ poskytnout explicitní implementaci pro každého člena rozhraní instance – nemůže použít výchozí implementaci poskytovanou rozhraním. Přidání výchozího člena instance do rozhraní, které ref struct implementuje, vyžaduje ref struct přidání odpovídající implementace, což je změna způsobující chybu zdroje. Z těchto důvodů je třeba používat úsudek při přidávání člena do existujícího rozhraní.

    Poznámka:

    Pokud je vaše rozhraní implementované podle ref struct typů (je to možné v C# 13 a novějších), přidání jakéhokoli výchozího člena instance do rozhraní je pro tyto volající změnu způsobující chybu zdroje. ref struct musí poskytnout explicitní implementaci nového člena; nemůže se tedy vrátit k výchozí implementaci.

  • ZAKÁZÁNO: Změna hodnoty veřejné konstanty nebo člena výčtu

  • ZAKÁZÁNO: Změna typu vlastnosti, pole, parametru nebo návratové hodnoty

  • ZAKÁZÁNO: Přidání, odebrání nebo změna pořadí parametrů

  • ZAKÁZÁNO: Přidání nebo odebrání klíčového slova in, out nebo ref z parametru

  • ✔️ POVOLENO: Změna parametru ref na ref readonly

    Změna parametru z ref na ref readonly je kompatibilní se zdrojovým kódem pro stávající místa volání, která předávají argumenty s modifikátorem ref – tato volání se dále budou kompilovat beze změny. Na rozdíl od změny ref na in parametr ref readonly neumožňuje volajícím tichým způsobem předávat hodnoty rvalue (jiné než proměnné); kompilátor vydá upozornění, pokud argument není proměnná. Existující ref volací místa zůstávají platná.

  • DISALLOWED: Změna parametru in na ref readonly

    Volání míst, která předávají in argumenty bez modifikátoru in (který kompilátor povoluje pro in parametry), zobrazí se upozornění, když se parametr změní na ref readonly, protože ref readonly vyžaduje, aby argument byl předán jako reference. Volající, kteří považují upozornění za chyby, zažijí změnu, která naruší zdrojový kód.

  • DISALLOWED: Přejmenování parametru (včetně změny jeho/její velikosti písmen)

    To se považuje za zásadní ze dvou důvodů:

  • ZAKÁZÁNO: Změna z návratové ref hodnoty na návratovou ref readonly hodnotu

  • ❌️ NEPOVOLENÉ: Změna vrácené hodnoty z ref readonly na ref u virtuální metody nebo rozhraní

  • ZAKÁZÁNO: Přidání nebo odebrání abstrakce ze člena

  • ZAKÁZÁNO: Odebrání virtuálního klíčového slova ze člena

  • ZAKÁZÁNO: Přidání virtuálního klíčového slova do člena

    I když to často není zásadní změna, protože kompilátor jazyka C# má tendenci generovat instrukce callvirt Intermediate Language (IL) pro volání nevirtuální metody (callvirt provádí kontrolu null, zatímco normální volání není), toto chování není z několika důvodů neměnné:

    • Jazyk C# není jediný jazyk, na který se .NET zaměřuje.
    • Kompilátor jazyka C# se stále častěji snaží optimalizovat callvirt na normální volání, kdykoli cílová metoda není virtuální a pravděpodobně není null (například metoda, ke které lze přistupovat prostřednictvím operátoru šíření ?. null).

    Vytvoření metody virtuální znamená, že kód příjemce by ji často volal nevirtuálně.

  • ZAKÁZÁNO: Vytvoření abstraktního virtuálního člena

    Virtuální člen poskytuje implementaci metody, kterou lze přepsat odvozenou třídou. Abstraktní člen neposkytuje žádnou implementaci a musí být překonfigurován.

  • ZAKÁZÁNO: Přidání zapečetěného klíčového slova do člena rozhraní

    Přidání sealed do výchozího členu rozhraní způsobí, že není virtuální, což brání volání implementace odvozeného typu daného člena.

  • ZAKÁZÁNO: Přidání abstraktního člena do veřejného typu, který má přístupné (veřejné nebo chráněné) konstruktory a který není zapečetěn

  • ZAKÁZÁNO: Přidání nebo odebrání statického klíčového slova ze člena

  • DISALLOWED: Přidání přetížení, které vylučuje existující přetížení a definuje jiné chování

    Tím se způsobí problémy u stávajících klientů, kteří byli vázáni na předchozí přetížení. Pokud má například třída jednu verzi metody, která přijímá UInt32, stávající příjemce úspěšně vytvoří vazbu na toto přetížení při předání Int32 hodnoty. Pokud ale přidáte přetížení, které přijme Int32, při rekompilaci nebo použití pozdní vazby kompilátor nyní přiřadí nové přetížení. Pokud se liší výsledky chování, může se jednat o zásadní změnu.

  • VYŽADUJE ÚSUDEK: Přidání OverloadResolutionPriorityAttribute do stávajícího přetížení nebo změna priority

    Vliv OverloadResolutionPriorityAttribute na rozlišení přetížení na úrovni zdroje: volající, kteří rekompilují, se mohou přeložit na jiné přetížení než dříve. Zamýšleným použitím je přidání atributu do nového, lepšího přetížení, aby ho kompilátor preferoval před existujícími. Přidání do existujícího přetížení nebo změna hodnoty priority u již přiřazeného přetížení může být změnou, která může narušit kompatibilitu zdrojového kódu, protože volající, kteří překompilují, mohou způsobit změnu chování.

  • ✔️ POVOLENO: Přidání allows ref struct protimodifikačního omezení do parametru obecného typu

    Přidáním allows ref struct rozbalíte typy, které lze použít jako argumenty typů tím, že povolíte ref struct typy. Stávající volající používající argumenty jiného než ref struct typu nejsou ovlivněni. Obecná metoda nebo typ musí dodržovat pravidla bezpečnosti ref pro všechny instance tohoto parametru typu.

  • DISALLOWED: Odstranění allows ref struct anti-omezení z parametru obecného typu

    Odebrání allows ref struct omezuje, které typy mohou volající používat jako argumenty typu. Každý volající, který předává ref struct jako argument typu, se již nebude kompilovat.

  • DISALLOWED: Přidání konstruktoru do třídy, která dříve neměla žádný konstruktor, bez přidání konstruktoru bez parametrů

  • ❌️ NEPOVOLENÉ: Přidání pouze pro čtení do textového pole

  • ZAKÁZÁNO: Snížení viditelnosti člena

    To zahrnuje snížení viditelnosti chráněného členu, pokud jsou dostupné (public nebo protected) konstruktory a typ nenízapečetěn. Pokud tomu tak není, omezení viditelnosti chráněného člena je povoleno.

    Zvýšení viditelnosti člena je povoleno.

  • ZAKÁZÁNO: Změna typu člena

    Návratovou hodnotu metody nebo typu vlastnosti nebo pole nelze změnit. Například deklarace metody, která vrací Object, nelze změnit, aby vracela String, a obráceně.

  • DISALLOWED: Přidání pole instance do struktury, která neobsahuje žádná nepubliková pole

    Pokud struktura obsahuje pouze veřejná pole nebo nemá vůbec žádná pole, volající mohou deklarovat místní hodnoty tohoto typu struktury bez volání konstruktoru struktury nebo první inicializace místního na default(T), pokud jsou všechna veřejná pole nastavena na strukturu před prvním použitím. Přidání jakýchkoli nových polí – veřejných nebo soukromých – do takové struktury je změna narušující kompatibilitu zdroje pro volající, protože kompilátor bude požadovat inicializaci dalších polí.

    Dodatečně, přidání jakýchkoli nových polí – veřejných nebo neveřejných – do struktury bez polí nebo pouze veřejných polí je binární změna zásadní pro volající, kteří použili [SkipLocalsInit] na svůj kód. Vzhledem k tomu, že kompilátor nebyl informován o těchto polích v době kompilace, mohl emitovat IL, který strukturu plně neinicializuje, což vede k vytvoření struktury z neinicializovaných dat zásobníku.

    Pokud má struktura jakákoli nepublikovaná pole, kompilátor již vynucuje inicializaci prostřednictvím konstruktoru nebo default(T)a přidání nových polí instance není zásadní změnou.

  • ZAKÁZÁNO: Spuštění existující události, když nebyla nikdy dříve spuštěna

Změny chování

Shromáždění

  • ✔️ POVOLENO: Učinit sestavení přenosným, pokud jsou stále podporovány stejné platformy

  • ZAKÁZÁNO: Změna názvu sestavení

  • ZAKÁZÁNO: Změna veřejného klíče sestavení

Vlastnosti, pole, parametry a návratové hodnoty

  • ✔️ POVOLENO: Změna hodnoty vlastnosti, pole, návratové hodnoty nebo out parametru na odvozenější typ

    Například metoda, která vrací typ Object může vrátit String instanci. (Podpis metody se však nemůže změnit.)

  • ✔️ POVOLENO: Zvýšení rozsahu přijatých hodnot pro vlastnost nebo parametr, pokud člen není virtuální

    Zatímco rozsah hodnot, které lze předat metodě nebo je člen může vrátit, se může rozšířit, typ parametru nebo člena nemůže. Například zatímco hodnoty předané metodě mohou rozšířit z 0-124 na 0-255, typ parametru se nemůže změnit z Byte na Int32.

  • DISALLOWED: Rozšíření rozsahu přijatých hodnot pro vlastnost nebo parametr, pokud je člen virtuální

    Tato změna přeruší stávající přepsané členy, které nebudou správně fungovat pro rozšířený rozsah hodnot.

  • DISALLOWED: Snížení rozsahu platných hodnot pro vlastnosti nebo parametry

  • DISALLOWED: Zvýšení rozsahu vrácených hodnot pro vlastnost, pole, návratovou hodnotu nebo out parametr

  • DISALLOWED: Změna vrácených hodnot pro vlastnost, pole, návratovou hodnotu metody nebo výstupní parametr

  • DISALLOWED: Změna výchozí hodnoty vlastnosti, pole nebo parametru

    Změna nebo odebrání výchozí hodnoty parametru nezpůsobí binární nekompatibilitu. Odebrání výchozí hodnoty parametru způsobí narušení zdrojového kódu a změna výchozí hodnoty parametru může vést k narušení chování po rekompilaci.

    Z tohoto důvodu je odebrání výchozích hodnot parametru přijatelné v konkrétním případě "přesunutí" těchto výchozích hodnot do nového přetížení metody, aby se eliminovala nejednoznačnost. Představte si například existující metodu MyMethod(int a = 1). Pokud zavádíte přetížení MyMethod se dvěma volitelnými parametry a a bmůžete zachovat kompatibilitu přesunutím výchozí hodnoty a do nového přetížení. Nyní jsou dvě přetížení MyMethod(int a) a MyMethod(int a = 1, int b = 2). Tento model umožňuje kompilovat MyMethod().

  • ZAKÁZÁNO: Změna přesnosti číselné návratové hodnoty

  • VYŽADUJE ROZSUDEK: Změna analýzy vstupu a vyvolání nových výjimek (i když není v dokumentaci uvedeno chování analýzy

  • ZAKÁZÁNO: Přidání nebo odebrání typů případů z union deklarace

    Přidání nebo odebrání typu případu ze union typu způsobuje binární nekompatibilitu i nekompatibilitu zdrojového kódu.

    Po přidání typu případu už testy porovnávání vzorů nejsou vyčerpávající. Kompilátor označí výrazy pro porovnávání vzorů jako neúplné. Neočekávané hodnoty během běhu způsobují výjimky za provozu. Odebrání typu případu odebere deklaraci konstruktoru pro tento typ případu.

Výjimky

  • ✔️ POVOLENO: Vyvolání odvozenější výjimky než existující výjimka

    Vzhledem k tomu, že nová výjimka je podtřídou existující výjimky, předchozí kód zpracování výjimek bude nadále zpracovávat výjimku. Například v .NET Framework 4 začaly metody vytváření a načítání kultury vyvolávat CultureNotFoundException místo ArgumentException, pokud nelze najít kulturu. Vzhledem k tomu, že CultureNotFoundException se odvozuje z ArgumentException, je to přijatelná změna.

  • ✔️ POVOLENO: Vyvolání konkrétnější výjimky než NotSupportedException, NotImplementedExceptionNullReferenceException

  • ✔️ POVOLENO: Vyvolání výjimky, která je považována za neobnovitelnou

    Neopravitelné výjimky by neměly být zachyceny, ale místo toho by se měly zpracovávat centrální obsluhou na vysoké úrovni. Uživatelé proto nemají kód, který tyto explicitní výjimky zachytí. Neopravitelné výjimky jsou:

  • ✔️ POVOLENO: Vyvolání nové výjimky v nové cestě kódu

    Výjimka se musí vztahovat pouze na novou cestu kódu, která se spouští s novými hodnotami nebo stavem parametrů a která nemůže být spuštěna existujícím kódem, který cílí na předchozí verzi.

  • ✔️ POVOLENO: Odebrání výjimky pro povolení robustnějšího chování nebo nových scénářů

    Například metodu Divide , která dříve zpracovávala pouze kladné hodnoty a hodila ArgumentOutOfRangeException jinak, lze změnit tak, aby podporovala záporné i kladné hodnoty bez vyvolání výjimky.

  • ✔️ POVOLENO: Změna textu chybové zprávy

    Vývojáři by se neměli spoléhat na text chybových zpráv, které se také mění v závislosti na jazykové verzi uživatele.

  • ZAKÁZÁNO: Vyvolání výjimky v jiném případě, který není uvedený výše

  • ZAKÁZÁNO: Odebrání výjimky v jiném případě, který není uveden výše

Atributy

  • ✔️ POVOLENO: Změna hodnoty atributu, který není pozorovatelný

  • ZAKÁZÁNO: Změna hodnoty atributu, který je pozorovatelný

  • VYŽADUJE ÚSUDEK: Odebrání atributu

    Ve většině případů je odebrání atributu (například NonSerializedAttribute) zásadní změnou.

Podpora platformy

  • ✔️ POVOLENO: Podpora operace na platformě, která se dříve nepodporovala

  • ZAKÁZÁNO: Již nepodporuje nebo nyní vyžaduje konkrétní balíček Service Pack pro operaci, která byla dříve podporována na platformě.

Změny interní implementace

  • VYŽADUJE ÚSUDEK: Změna povrchové plochy interního typu

    Tyto změny jsou obecně povoleny, i když přerušují soukromé reflexe. V některých případech, kdy oblíbené knihovny třetích stran nebo velký počet vývojářů závisí na interních rozhraních API, nemusí být tyto změny povolené.

  • VYŽADUJE POSOUZENÍ: Změna interní implementace člena

    Tyto změny jsou obecně povolené, i když přerušují soukromé reflexe. V některých případech, kdy zákaznický kód často závisí na soukromé reflexi nebo kdy změna představuje nežádoucí vedlejší účinky, nemusí být tyto změny povoleny.

  • ✔️ POVOLENO: Zlepšení výkonu operace

    Schopnost upravit výkon operace je nezbytná, ale takové změny můžou přerušit kód, který závisí na aktuální rychlosti operace. To platí zejména pro kód, který závisí na načasování asynchronních operací. Změna výkonu by neměla mít žádný vliv na jiné chování daného rozhraní API; jinak bude změna narušující.

  • ✔️ POVOLENO: Nepřímo (a často nepříznivě) mění výkon operace.

    Pokud daná změna není z nějakého jiného důvodu považována za kritickou změnu, je to akceptovatelné. Často je potřeba provést akce, které můžou zahrnovat další operace nebo které přidávají nové funkce. To bude téměř vždy mít vliv na výkon, ale může být nezbytné, aby příslušné rozhraní API fungovalo podle očekávání.

  • Nepovoleno: Změna synchronního rozhraní API na asynchronní (a naopak)

Změny kódu

  • ✔️ POVOLENO: Přidání parametrů do parametru

  • Nepovoleno: Změna struktury na třídu a naopak

  • DISALLOWED: Přidání zaškrtnutého příkazu do bloku kódu

    Tato změna může způsobit, že kód, který se dříve spustil, vyvolá výjimku OverflowException a je to nepřijatelné.

  • ZAKÁZÁNO: Odebrání params z parametru

  • NEPOVOLENO: Změna typu kolekce u parametru params

    Počínaje C# 13 params parametry podporují typy kolekcí jiné než pole, včetně Span<T>, ReadOnlySpan<T>, struktur nebo typů tříd, které implementují IEnumerable<T> s přístupným konstruktorem bez parametrů a metodou instance Add, a konkrétní typy rozhraní, jako jsou IList<T>. Změna typu kolekce existujícího params parametru (například z params T[] na params ReadOnlySpan<T>) změní signaturu IL metody a jedná se o binární zásadní změnu. Volání sestavená s předchozí verzí je potřeba překompilovat.

  • ✔️ POVOLENO: Převod metody rozšíření na syntaxi člena bloku rozšíření

    Počínaje C# 14 můžete deklarovat rozšiřující členy pomocí bloků extension kromě starší syntaxe this parametru. Oba formuláře generují identické IL, takže volající mezi nimi nemohou rozlišovat. Převod existujících metod rozšíření na novou syntaxi bloku rozšíření je binární a zdroj kompatibilní.

  • ZAKÁZÁNO: Změna pořadí, ve kterém se události aktivují

    Vývojáři můžou přiměřeně očekávat, že se události aktivují ve stejném pořadí a kód vývojáře často závisí na pořadí, ve kterém se události aktivují.

  • ZAKÁZÁNO: Odebrání vyvolání události u dané akce

  • ZAKÁZÁNO: Změna počtu uvedených volání událostí

  • DISALLOWED: Přidání FlagsAttribute do typu výčtu

Viz také