Aspekty verzí a aktualizací pro vývojáře v jazyce C#

Kompatibilita je důležitým cílem při přidávání nových funkcí do jazyka C#. Téměř ve všech případech je možné existující kód rekompilovat s novou verzí kompilátoru bez jakýchkoli problémů. Tým modulu runtime .NET má také cíl zajistit kompatibilitu aktualizovaných knihoven. V téměř všech případech, když se vaše aplikace spustí z aktualizovaného modulu runtime s aktualizovanými knihovnami, je chování naprosto stejné jako u předchozích verzí.

Jazyková verze použitá ke kompilaci aplikace obvykle odpovídá monikeru cílového modulu runtime (TFM) odkazovanému v projektu. Další informace o změně výchozí jazykové verze najdete v článku s názvem Konfigurace jazykové verze. Toto výchozí chování zajišťuje maximální kompatibilitu.

Při zavedení změn způsobujících chybu se klasifikují jako:

  • Binární změna způsobující chybu: Binární změna způsobující chybu způsobuje jiné chování, včetně možného chybového ukončení, ve vaší aplikaci nebo knihovně při spuštění pomocí nového modulu runtime. Abyste tyto změny mohli začlenit, musíte aplikaci znovu zkompilovat. Existující binární soubor nebude správně fungovat.
  • Změna způsobující chybu zdroje: Změna způsobující chybu zdroje změní význam zdrojového kódu. Před kompilací aplikace s nejnovější verzí jazyka je nutné provádět úpravy zdrojového kódu. Váš existující binární soubor se bude spouštět správně s novějším hostitelem a modulem runtime. Všimněte si, že pro syntaxi jazyka je zásadní změnou zdroje také změna chování, jak je definováno v zásadních změnách modulu runtime.

Když binární změna způsobující chybu ovlivní vaši aplikaci, musíte aplikaci znovu zkompilovat, ale nemusíte upravovat žádný zdrojový kód. Pokud změna způsobující chybu zdroje ovlivní vaši aplikaci, stávající binární soubor stále funguje správně v prostředích s aktualizovaným modulem runtime a knihovnami. Je však nutné provést změny zdrojového kódu pro překompilování s novou jazykovou verzí a modulem runtime. Pokud je změna způsobující chybu zdroje i binární chybu, musíte aplikaci znovu zkompilovat s nejnovější verzí a provést aktualizace zdroje.

Vzhledem k tomu, že chcete zabránit zásadním změnám týmem jazyka C# a týmem modulu runtime, je aktualizace aplikace obvykle otázkou aktualizace TFM a opětovného sestavení aplikace. Pro knihovny, které jsou distribuovány veřejně, byste ale měli pečlivě vyhodnotit zásady pro podporované TFM a podporované jazykové verze. Možná vytváříte novou knihovnu s funkcemi nalezenými v nejnovější verzi a potřebujete zajistit, aby ji mohly používat aplikace vytvořené pomocí předchozích verzí kompilátoru. Nebo možná upgradujete existující knihovnu a mnozí uživatelé ještě neupgradovali verze.

Představení zásadních změn v knihovnách

Když ve veřejném rozhraní API knihovny přijmete nové jazykové funkce, měli byste vyhodnotit, jestli přijetí této funkce představuje binární nebo zdrojovou změnu způsobující chybu pro uživatele vaší knihovny. Všechny změny interní implementace, které se nezobrazují v rozhraní public nebo protected rozhraní, jsou kompatibilní.

Poznámka:

Pokud pomocí této možnosti System.Runtime.CompilerServices.InternalsVisibleToAttribute povolíte zobrazení interních členů, můžou interní členové zavádět zásadní změny.

Binární změna způsobující chybu vyžaduje, aby uživatelé překompilovali svůj kód, aby mohli používat novou verzi. Představte si například tuto veřejnou metodu:

public double CalculateSquare(double value) => value * value;

Pokud do metody přidáte in modifikátor, jde o binární zásadní změnu:

public double CalculateSquare(in double value) => value * value;

Uživatelé musí znovu zkompilovat všechny aplikace, které používají metodu CalculateSquare , aby nová knihovna fungovala správně.

Změna způsobující chybu zdroje vyžaduje, aby uživatelé před opětovným kompilací změnili svůj kód. Představte si například tento typ:

public class Person
{
    public string FirstName { get; }
    public string LastName { get; }

    public Person(string firstName, string lastName) => (FirstName, LastName) = (firstName, lastName);

    // other details omitted
}

V novější verzi byste chtěli využít syntetizované členy generované pro record typy. Provedete následující změnu:

public record class Person(string FirstName, string LastName);

Předchozí změna vyžaduje změny pro libovolný typ odvozený z Person. Všechny tyto deklarace musí do svých deklarací přidat record modifikátor.

Dopad zásadních změn

Když do knihovny přidáte binární zásadní změnu , vynutíte všechny projekty, které používají vaši knihovnu k opětovnému kompilaci. Žádný zdrojový kód v těchto projektech se ale nemusí měnit. Výsledkem je, že dopad zásadní změny je pro každý projekt přiměřeně malý.

Když provedete změnu způsobující chybu zdroje v knihovně, budete potřebovat, aby všechny projekty udělaly změny zdroje, aby používaly novou knihovnu. Pokud potřebná změna vyžaduje nové jazykové funkce, vynutíte, aby se tyto projekty upgradovali na stejnou jazykovou verzi a TFM, které právě používáte. Pro uživatele jste vyžadovali více práce a možná jste je přinutili k upgradu.

Dopad jakékoli provedené změny způsobující chybu závisí na počtu projektů, které mají závislost na vaší knihovně. Pokud vaše knihovna interně používá několik aplikací, můžete reagovat na všechny zásadní změny ve všech ovlivněných projektech. Pokud je ale vaše knihovna veřejně stažená, měli byste vyhodnotit potenciální dopad a zvážit alternativy:

  • Můžete přidat nová rozhraní API, která paralelní existující rozhraní API.
  • Můžete zvážit paralelní sestavení pro různé TFM.
  • Můžete zvážit cílení na více verzí.