Uwaga
Dostęp do tej strony wymaga autoryzacji. Może spróbować zalogować się lub zmienić katalogi.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
W tym samouczku dowiesz się, co oznacza przechowywanie wersji na platformie .NET. Poznasz również czynniki, które należy wziąć pod uwagę podczas przechowywania wersji biblioteki, a także uaktualniania do nowej wersji biblioteki.
Wersja języka
Kompilator języka C# jest częścią zestawu .NET SDK. Domyślnie kompilator wybiera wersję języka C#zgodną z wybranym programem TFM dla projektu. Jeśli wersja zestawu SDK jest większa niż wybrana platforma, kompilator może użyć nowszej wersji językowej. Możesz zmienić wartość domyślną, ustawiając LangVersion
element w projekcie. Możesz dowiedzieć się, jak w naszym artykule o opcjach kompilatora.
Ostrzeżenie
LangVersion
Ustawienie elementu na latest
wartość jest niezalecone. Ustawienie latest
oznacza, że zainstalowany kompilator używa najnowszej wersji. Może to zmienić się z maszyny na maszynę, co sprawia, że kompilacje są zawodne. Ponadto włącza funkcje językowe, które mogą wymagać funkcji środowiska uruchomieniowego lub biblioteki, które nie są uwzględnione w bieżącym zestawie SDK.
Biblioteki autorskie
Jako deweloper, który utworzył biblioteki .NET do użytku publicznego, z pewnością byłeś w sytuacjach, w których trzeba wdrożyć nowe aktualizacje. Sposób wykonywania tego procesu ma wiele znaczenia, ponieważ musisz mieć pewność, że istnieje bezproblemowe przejście istniejącego kodu do nowej wersji biblioteki. Poniżej przedstawiono kilka kwestii, które należy wziąć pod uwagę podczas tworzenia nowej wersji:
Semantyczne wersjonowanie
Wersjonowanie semantyczne (w skrócie SemVer) to konwencja nazewnictwa stosowana do wersji twojej biblioteki w celu oznaczenia określonych wydarzeń kamieni milowych. W idealnym przypadku informacje o wersji udostępniane biblioteki powinny ułatwić deweloperom określenie zgodności ze swoimi projektami korzystającymi ze starszych wersji tej samej biblioteki.
Najbardziej podstawowym podejściem do SemVer jest 3-elementowy format MAJOR.MINOR.PATCH
, gdzie:
-
MAJOR
jest inkrementowana w przypadku wprowadzania niekompatybilnych zmian interfejsu API -
MINOR
jest zwiększany, gdy dodajesz funkcjonalność w sposób wstecznie kompatybilny -
PATCH
jest inkrementowane, gdy wprowadzane są poprawki usterek kompatybilnych wstecz
Istnieją również sposoby określania innych scenariuszy, na przykład wersji wstępnych, podczas stosowania informacji o wersjach do biblioteki .NET.
Zgodność z poprzednimi wersjami
W miarę wydawania nowych wersji biblioteki zgodność z poprzednimi wersjami będzie najprawdopodobniej jedną z głównych kwestii. Nowa wersja biblioteki jest zgodna źródłowo z poprzednią wersją, jeśli kod zależny od poprzedniej wersji po ponownym skompilowaniu może działać z nową wersją. Nowa wersja biblioteki jest zgodna binarnie, jeśli aplikacja zależna od starej wersji może bez ponownej kompilacji pracować z nową wersją.
Poniżej przedstawiono kilka kwestii, które należy wziąć pod uwagę podczas próby zachowania zgodności z poprzednimi wersjami biblioteki:
- Metody wirtualne: jeśli w nowej wersji zostanie utworzona metoda wirtualna, która nie jest wirtualna, oznacza to, że projekty, które zastępują tę metodę, będą musiały zostać zaktualizowane. Jest to ogromna zmiana powodująca niezgodność i zdecydowanie się jej odradza.
- Sygnatury metod: Gdy zaktualizowanie zachowania metody wymaga również zmiany jej sygnatury, zamiast tego powinieneś utworzyć jej przeciążenie, aby kod wywołujący tę metodę nadal działał. Zawsze można manipulować starym podpisem metody w celu wywołania nowego podpisu metody, aby implementacja pozostała spójna.
- Przestarzały atrybut: ten atrybut można użyć w kodzie, aby określić klasy lub składowe klasy, które są przestarzałe i prawdopodobnie zostaną usunięte w przyszłych wersjach. Dzięki temu deweloperzy korzystający z biblioteki są lepiej przygotowani do zmian powodujących niekompatybilność.
- Argumenty opcjonalne metody: kiedy wcześniej opcjonalne argumenty metody stają się obowiązkowe lub zmienia się ich wartość domyślna, cały kod, który nie uwzględnia tych argumentów, będzie musiał zostać zaktualizowany.
Uwaga
Wprowadzanie obowiązkowych argumentów opcjonalnych powinno mieć bardzo niewielki wpływ, zwłaszcza jeśli nie zmienia zachowania metody.
Im łatwiej jest umożliwić użytkownikom uaktualnienie do nowej wersji biblioteki, tym bardziej prawdopodobne jest, że będą one uaktualniać wcześniej.
Plik konfiguracji aplikacji
Jako deweloper platformy .NET istnieje bardzo duże prawdopodobieństwo, że zetknąłeś się z plikiem app.config
obecnym w większości typów projektów.
Ten prosty plik konfiguracji może przejść długą drogę do poprawy wdrażania nowych aktualizacji. Biblioteki powinny być zwykle projektowane w taki sposób, że informacje, które mogą być regularnie zmieniane, są przechowywane w app.config
pliku, w ten sposób po zaktualizowaniu takich informacji plik konfiguracji starszych wersji musi zostać zastąpiony nowym, bez konieczności ponownego komplikowania biblioteki.
Korzystanie z bibliotek
Jako deweloper korzystający z bibliotek .NET utworzonych przez innych deweloperów najprawdopodobniej wiesz, że nowa wersja biblioteki może nie być w pełni zgodna z projektem i często może się okazać, że trzeba zaktualizować kod, aby pracować z tymi zmianami.
Na szczęście dla Ciebie, język C# i ekosystem .NET zawierają funkcje i techniki, które pozwalają nam łatwo dostosować naszą aplikację, aby działała z nowymi wersjami bibliotek, które mogą wprowadzać zmiany powodujące niezgodność.
Przekierowanie powiązania zestawu
Możesz użyć pliku app.config , aby zaktualizować wersję biblioteki używanej przez aplikację. Dodając element nazywany przekierowaniem wiązania, możesz użyć nowej wersji biblioteki bez konieczności ponownego kompilowania aplikacji. W poniższym przykładzie pokazano, jak zaktualizować plik app.config aplikacji, aby użyć wersji 1.0.1
poprawki ReferencedLibrary
zamiast wersji 1.0.0
, z którą została pierwotnie skompilowana.
<dependentAssembly>
<assemblyIdentity name="ReferencedLibrary" publicKeyToken="32ab4ba45e0a69a1" culture="en-us" />
<bindingRedirect oldVersion="1.0.0" newVersion="1.0.1" />
</dependentAssembly>
Uwaga
Takie podejście będzie działać tylko wtedy, gdy nowa wersja programu ReferencedLibrary
jest binarnie zgodna z twoją aplikacją.
Zobacz sekcję Zgodność z poprzednimi wersjami powyżej, aby zapoznać się ze zmianami podczas określania zgodności.
nowe
Używasz modyfikatora new
, aby ukryć dziedziczone składowe klasy bazowej. Jest to jeden ze sposobów, w jaki klasy pochodne mogą reagować na aktualizacje w klasach bazowych.
Spójrz na następujący przykład:
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();
}
Wyjście
A base method
A derived method
W powyższym przykładzie można zobaczyć, jak DerivedClass
ukrywa metodę MyMethod
w BaseClass
.
Oznacza to, że gdy klasa bazowa w nowej wersji biblioteki dodaje składową, która już istnieje w klasie pochodnej, możesz po prostu użyć new
modyfikatora w składowej klasy pochodnej, aby ukryć składową klasy bazowej.
Jeśli nie zostanie określony modyfikator new
, klasa pochodna domyślnie ukryje sprzeczne elementy członkowskie w klasie bazowej, i choć zostanie wygenerowane ostrzeżenie kompilatora, kod będzie nadal kompilowany. Oznacza to, że po prostu dodanie nowych elementów członkowskich do istniejącej klasy sprawia, że nowa wersja biblioteki źródłowej i binarnej jest zgodna z kodem, który jest od niego zależny.
zastąpienie
Modyfikator override
oznacza, że implementacja pochodna rozszerza implementację członka klasy bazowej, zamiast ją ukrywać. Składowa klasy bazowej musi mieć zastosowany modyfikator virtual
.
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()}");
}
Wyjście
Base Method One: Method One
Derived Method One: Derived Method One
override
Modyfikator jest oceniany w czasie kompilacji, a kompilator zgłosi błąd, jeśli nie znajdzie wirtualnego składnika do zastąpienia.
Twoja wiedza na temat omówionych technik i zrozumienia sytuacji, w których można je zastosować, znacząco przyczyni się do ułatwienia przejścia między wersjami biblioteki.