Megjegyzés
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhat bejelentkezni vagy módosítani a címtárat.
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhatja módosítani a címtárat.
Ebben az oktatóanyagban megtudhatja, mit jelent a verziószámozás a .NET-ben. Megismerheti azokat a tényezőket is, amelyeket figyelembe kell vennie a tár verziószámozása, valamint a tár új verziójára való frissítés során.
Nyelvi verzió
A C#-fordító a .NET SDK része. A fordító alapértelmezés szerint a projekthez választott TFM-nek megfelelő C#-nyelvi verziót választja ki. Ha az SDK-verzió nagyobb, mint a választott keretrendszer, a fordító nagyobb nyelvi verziót használhat. Az alapértelmezett beállítást a projekt elemének LangVersion beállításával módosíthatja. A fordítási lehetőségekről szóló cikkünkből megtudhatja, hogyan.
Figyelmeztetés
Az LangVersion elem latest beállítása nem ajánlott. A latest beállítás azt jelenti, hogy a telepített fordító a legújabb verzióját használja. Ez gépről gépre változhat, így a buildek megbízhatatlanok lesznek. Emellett olyan nyelvi funkciókat is lehetővé tesz, amelyekhez futásidejű vagy tárfunkciókra lehet szükség, amelyek nem szerepelnek az aktuális SDK-ban.
Könyvtárak létrehozása
Fejlesztőként, aki nyilvános használatra hozott létre .NET-kódtárakat, nagy valószínűséggel olyan helyzetekben volt, amikor új frissítéseket kell létrehoznia. A folyamat menete sokat számít, mivel gondoskodnia kell arról, hogy a meglévő kód zökkenőmentesen átálljon a kódtár új verziójára. Az alábbi szempontokat érdemes figyelembe venni egy új kiadás létrehozásakor:
Szemantikus verziószámozás
A szemantikus verziószámozás (röviden SemVer) a kódtár verzióira alkalmazott elnevezési konvenció, amely konkrét mérföldköves eseményeket jelez. Ideális esetben a kódtár által megadott verzióinformációknak segíteniük kell a fejlesztőknek annak megállapításában, hogy az adott kódtár régebbi verzióit használó projektjeik kompatibilisek-e.
A SemVer legalapvetőbb megközelítése a 3 összetevő formátuma MAJOR.MINOR.PATCH, ahol:
-
MAJORinkompatibilis API-módosítások végrehajtásakor növekszik -
MINORa funkció visszamenőlegesen kompatibilis hozzáadásakor növekszik -
PATCHa visszafelé kompatibilis hibajavítások létrehozásakor növekszik
A verziónövekmények ismertetése példákkal
Az egyes verziószámok növelésének pontosítása érdekében az alábbiakban konkrét példákat talál:
FŐverzió-növekmények (nem kompatibilis API-módosítások)
Ezekhez a módosításokhoz a felhasználóknak módosítaniuk kell a kódjukat az új verzió használatához:
Nyilvános metódus vagy tulajdonság eltávolítása:
// Version 1.0.0 public class Calculator { public int Add(int a, int b) => a + b; public int Subtract(int a, int b) => a - b; // This method exists } // Version 2.0.0 - MAJOR increment required public class Calculator { public int Add(int a, int b) => a + b; // Subtract method removed - breaking change! }Metódus-aláírások módosítása:
// Version 1.0.0 public void SaveFile(string filename) { } // Version 2.0.0 - MAJOR increment required public void SaveFile(string filename, bool overwrite) { } // Added required parameterA meglévő metódusok viselkedésének módosítása az elvárásokat megszegő módon:
// Version 1.0.0 - returns null when file not found public string ReadFile(string path) => File.Exists(path) ? File.ReadAllText(path) : null; // Version 2.0.0 - MAJOR increment required public string ReadFile(string path) => File.ReadAllText(path); // Now throws exception when file not found
A MINOR verzió növekményei (visszamenőlegesen kompatibilis funkciók)
Ezek a módosítások új funkciókat adnak hozzá a meglévő kód feltörése nélkül:
Új nyilvános metódusok vagy tulajdonságok hozzáadása:
// Version 1.0.0 public class Calculator { public int Add(int a, int b) => a + b; } // Version 1.1.0 - MINOR increment public class Calculator { public int Add(int a, int b) => a + b; public int Multiply(int a, int b) => a * b; // New method added }Új túlterhelések hozzáadása:
// Version 1.0.0 public void Log(string message) { } // Version 1.1.0 - MINOR increment public void Log(string message) { } // Original method unchanged public void Log(string message, LogLevel level) { } // New overload addedVálasztható paraméterek hozzáadása meglévő metódusokhoz:
// Version 1.0.0 public void SaveFile(string filename) { } // Version 1.1.0 - MINOR increment public void SaveFile(string filename, bool overwrite = false) { } // Optional parameterFeljegyzés
Ez egy forráskompatibilis változás, de bináris kompatibilitástörő változás. A kódtár felhasználóinak újrafordítást kell végeznie ahhoz, hogy megfelelően működjön. Ezt sok kódtár csak a főverziók módosításainál veszi figyelembe, az alverziók módosításait nem.
A PATCH-verzió növekményei (visszamenőlegesen kompatibilis hibajavítások)
Ezek a módosítások új funkciók hozzáadása vagy a meglévő funkciók feltörése nélkül oldják meg a problémákat:
Hiba kijavítása egy meglévő metódus implementációjában:
// Version 1.0.0 - has a bug public int Divide(int a, int b) { return a / b; // Bug: doesn't handle division by zero } // Version 1.0.1 - PATCH increment public int Divide(int a, int b) { if (b == 0) throw new ArgumentException("Cannot divide by zero"); return a / b; // Bug fixed, behavior improved but API unchanged }Az API-t nem módosító teljesítménybeli fejlesztések:
// Version 1.0.0 public List<int> SortNumbers(List<int> numbers) { return numbers.OrderBy(x => x).ToList(); // Slower implementation } // Version 1.0.1 - PATCH increment public List<int> SortNumbers(List<int> numbers) { var result = new List<int>(numbers); result.Sort(); // Faster implementation, same API return result; }
A fő alapelv a következő: ha a meglévő kód módosítások nélkül is használhatja az új verziót, az egy MINOR vagy PATCH frissítés. Ha a meglévő kódot módosítani kell az új verzió használatához, az egy FŐ frissítés.
A .NET-tár verzióinformációinak alkalmazásakor más forgatókönyveket is megadhat, például a kiadás előtti verziókat.
Visszamenőleges kompatibilitás
A kódtár új verzióinak kiadásakor valószínűleg a korábbi verziókkal való kompatibilitás lesz az egyik fő probléma. A kódtár új verziója kompatibilis az előző verzióval, ha az előző verziótól függő kód újrafordításkor képes az új verzióval dolgozni. A kódtár új verziója binárisan kompatibilis, ha egy, a régi verziótól függő alkalmazás újrafordítás nélkül használhatja az új verziót.
Az alábbi szempontokat érdemes figyelembe venni a kódtár régebbi verzióival való kompatibilitás fenntartásakor:
- Virtuális metódusok: Ha az új verzió során virtuális metódust nem virtuálissá alakít, az azt jelenti, hogy azoknak a projekteknek, amelyek felülírják azt a metódust, frissítésre lesz szükségük. Ez egy hatalmas törés változás, és erősen elriasztja.
- Metódus-aláírások: A metódus viselkedésének frissítésekor az aláírását is módosítania kell, ehelyett túlterhelést kell létrehoznia, hogy a metódusba behívott kód továbbra is működjön. A régi metódus-aláírást bármikor módosíthatja, hogy behívja az új metódus-aláírást, hogy a végrehajtás konzisztens maradjon.
- Elavult attribútum: A kódban ezt az attribútumot használhatja elavult osztályok vagy osztálytagok megadására, amelyek a későbbi verziókban valószínűleg el lesznek távolítva. Ez biztosítja, hogy a kódtárat használó fejlesztők jobban felkészüljenek a kompatibilitást megszakító változásokra.
- Választható metódusargumentumok: Ha a korábban választható metódusargumentumokat kötelezővé teszi, vagy módosítja az alapértelmezett értéket, akkor az argumentumokat nem tartalmazó összes kódot frissíteni kell.
Feljegyzés
A kötelező argumentumok opcionálissá tétele nagyon kevés hatással kellene, hogy legyen, különösen ha nem változtatja meg a módszer viselkedését.
Minél könnyebben frissíthetnek a felhasználóinak a könyvtár új verziójára, annál valószínűbb, hogy hamarabb frissítenek.
Alkalmazáskonfigurációs fájl
.NET-fejlesztőként nagy az esély arra, hogy a app.config legtöbb projekttípusban megtalálható fájllal találkozott.
Ez az egyszerű konfigurációs fájl sokat segíthet az új frissítések bevezetésének javításában. A kódtárakat általában úgy kell megtervezni, hogy a valószínűleg rendszeresen változó információk a fájlban app.config legyenek tárolva, így az ilyen információk frissítésekor a régebbi verziók konfigurációs fájlját csak az újra kell cserélni anélkül, hogy újra kellene állítani a tárat.
Könyvtárak felhasználása
Olyan fejlesztőként, aki más fejlesztők által készített .NET-kódtárakat használ, nagy valószínűséggel tisztában van azzal, hogy a kódtár új verziója nem feltétlenül kompatibilis a projekttel, és gyakran előfordulhat, hogy frissítenie kell a kódot, hogy működjön ezekkel a módosításokkal.
Szerencséje van, a C# és a .NET-ökoszisztéma olyan funkciókkal és technikákkal rendelkezik, amelyek lehetővé teszik, hogy egyszerűen frissítsük az alkalmazást a kódtárak új verzióival való együttműködésre, amelyek kompatibilitástörő változásokat eredményezhetnek.
Szerelvénykötés átirányítása
Az app.config fájllal frissítheti az alkalmazás által használt tár verzióját. Az úgynevezett kötésátirányítás hozzáadásával az alkalmazás újrafordítása nélkül használhatja az új kódtár-verziót. Az alábbi példa bemutatja, hogyan frissíthetné az alkalmazás app.config fájlját, hogy a 1.0.1 javítóverzióját használja ReferencedLibrary helyett a 1.0.0 verzióval, amivel eredetileg le lett fordítva.
<dependentAssembly>
<assemblyIdentity name="ReferencedLibrary" publicKeyToken="32ab4ba45e0a69a1" culture="en-us" />
<bindingRedirect oldVersion="1.0.0" newVersion="1.0.1" />
</dependentAssembly>
Feljegyzés
Ez a megközelítés csak akkor működik, ha az új verzió ReferencedLibrary binárisan kompatibilis az alkalmazással.
A kompatibilitás meghatározásakor a fenti Visszamenőleges kompatibilitás című szakaszból megtudhatja, hogy milyen változásokra kell figyelnie.
Új
A new módosítót az alaposztály örökölt tagjainak elrejtésére használja. A származtatott osztályok így reagálhatnak az alaposztályok frissítéseire.
Vizsgálja meg az alábbi példát:
public class BaseClass
{
public void MyMethod()
{
Console.WriteLine("A base method");
}
}
public class DerivedClass : BaseClass
{
public new void MyMethod()
{
Console.WriteLine("A derived method");
}
}
public static void Main()
{
BaseClass b = new BaseClass();
DerivedClass d = new DerivedClass();
b.MyMethod();
d.MyMethod();
}
Kimenet
A base method
A derived method
A fenti példában láthatja, hogyan DerivedClass elrejti a MyMethod metódust BaseClass jelenlétében.
Ez azt jelenti, hogy ha egy erőforrástár új verziójában egy alaposztály hozzáad egy olyan tagot, amely már létezik a származtatott osztályban, egyszerűen használhatja a new származtatott osztálytag módosítóját az alaposztálytag elrejtéséhez.
Ha nincs new módosító megadva, a származtatott osztály alapértelmezés szerint elrejti az ütköző tagokat az alaposztályban, bár a fordító figyelmeztetést ad, a kód továbbra is lefordul. Ez azt jelenti, hogy ha egyszerűen új tagokat ad hozzá egy meglévő osztályhoz, akkor a kódtár új verziója forrásként és binárisan is kompatibilis lesz az attól függő kóddal.
felülbírál
A override módosító azt jelenti, hogy a származtatott implementáció nem elrejti, hanem kibővíti egy alaposztálytag implementálását. Az alaposztály tagjának alkalmaznia kell a virtual módosítót.
public class MyBaseClass
{
public virtual string MethodOne()
{
return "Method One";
}
}
public class MyDerivedClass : MyBaseClass
{
public override string MethodOne()
{
return "Derived Method One";
}
}
public static void Main()
{
MyBaseClass b = new MyBaseClass();
MyDerivedClass d = new MyDerivedClass();
Console.WriteLine($"Base Method One: {b.MethodOne()}");
Console.WriteLine($"Derived Method One: {d.MethodOne()}");
}
Kimenet
Base Method One: Method One
Derived Method One: Derived Method One
A override módosító kiértékelése fordításkor történik, és a fordító hibát jelez, ha nem talál egy felülbírálandó virtuális tagot.
Ha ismeri a tárgyalt technikákat, és tisztában van azokkal a helyzetekkel, amelyekben használni szeretné őket, hosszú utat fog tenni a tár verziói közötti átmenet enyhítése felé.