Newsy .NET — .NET 11 RC1, unie w C# 15 i CS8509 (wrzesień 2026)

W pierwszym odcinku Newsów .NET napisałem, że w C# 15 brak jednego przypadku unii w switch to błąd kompilacji. We wrześniu wyszedł .NET 11 Release Candidate 1,
więc uruchomiłem to na prawdziwym SDK. Program się skompilował, wypisał dwie linijki i wywrócił się na trzeciej a kompilator przez cały czas wiedział, którego przypadku brakuje, i napisał to po imieniu.
To jest sprostowanie i zarazem pierwszy z ośmiu newsów z września. Każdy fragment
kodu w tym wpisie został uruchomiony na .NET 11 RC1 (11.0.100-rc.1.26425.128,
30.09.2026) wyniki poniżej to realny output konsoli, nie przepisana dokumentacja.
Pozostałe pozycje, zebrane z pierwotnych źródeł: paczka NuGet, która wykonuje swój kod w chwili otwarcia projektu, nowy certyfikat Microsoftu, dzień, w którym kończą się dwie wersje .NET naraz, i trzy zmiany w GitHub Copilot, których nikt nie włączał.
.NET 11 RC1: na produkcję już wolno, C# 15 domyślnie
8 września 2026 Microsoft wypuścił .NET 11 Release Candidate 1 z licencją
go-live oficjalnie można go używać na produkcji i liczyć na wsparcie. Druga
zmiana jest ważniejsza dla codziennej pracy: w RC1 C# 15 jest domyślną wersją
języka dla projektów na net11.0. Nie dopisujesz już <LangVersion>preview</LangVersion> — unie, zamknięte hierarchie i etykietowany break działają od ręki. Sprawdziłem to wprost: żaden z plików poniżej nie ma flagi preview.
Finalna wersja wychodzi na .NET Conf, która startuje 10 listopada. Zapamiętaj tę
datę, wraca niżej, w dużo mniej przyjemnym kontekście.
Zasada:
RC z licencją go-live to moment, w którym warto zacząć testy na własnym
kodzie, nie po premierze. To, co znajdziesz teraz, możesz jeszcze zgłosić.
Unie w C# 15 – składnia finalna jest inna niż w odcinku #1
W odcinku pierwszym pokazałem „przewidywaną składnię” unii: warianty zadeklarowane w klamrach, wewnątrz typu. Zaznaczyłem, że to faza projektowania. Zmieniło się — finalna unia wylicza typy, które już istnieją, a przypadki są zwykłymi rekordami:
Shape[] shapes = [new Circle(1), new Square(2)];
foreach (Shape s in shapes)
{
Console.WriteLine($"{s.Value}: {Area(s):F2}");
}
static double Area(Shape s) => s switch
{
Circle c => Math.PI * c.Radius * c.Radius,
Square sq => sq.Side * sq.Side
};
public record Circle(double Radius);
public record Square(double Side);
public union Shape(Circle, Square);Circle { Radius = 1 }: 3,14
Square { Side = 2 }: 4,00Cała unia to ostatnia linijka. Circle i Square nie wiedzą, że do niej należą —
możesz ich używać także poza nią, co odróżnia unię od klasycznej hierarchii
dziedziczenia. switch nie ma gałęzi domyślnej (_ =>), bo kompilator zna zamknięty
zbiór przypadków. Jeśli wyrażenia switch z wzorcami typów są dla Ciebie nowe, zacznij od Switch w C# — od klasycznej instrukcji po pattern matching,
a o samych rekordach przeczytasz w Class, struct czy record w C#?.
Jeden szczegół, który wyszedł dopiero przy uruchomieniu: w Console.WriteLine stoi s.Value, nie samo s. Pierwsza wersja tego pliku miała {s} i wypisywała Shape: 3,14 — unia zamieniona na tekst podaje nazwę unii, a nie przypadku. Do tego, co jest w środku, sięgasz przez właściwość Value.
Zasada:
unia łączy typy, które już masz. Nie przepisujesz klas pod nią, dopisujesz
jedną linijkę, która mówi, z czego się składa.
Pułapka #1: CS8509 to ostrzeżenie, nie błąd
A teraz właściwe sprostowanie. Dopisuję trzeci wariant, trójkąt do unii i do tablicy,
ale switch zostawiam bez zmian. Dokładnie tak, jak wygląda to w prawdziwym projekcie, gdzie takich switch-y jest dwadzieścia w różnych plikach:
Shape[] shapes = [new Circle(1), new Square(2), new Triangle(3, 4)];
foreach (Shape s in shapes)
{
Console.WriteLine($"{s.Value}: {Area(s):F2}");
}
static double Area(Shape s) => s switch
{
Circle c => Math.PI * c.Radius * c.Radius,
Square sq => sq.Side * sq.Side
};
public record Circle(double Radius);
public record Square(double Side);
public record Triangle(double Base, double Height);
public union Shape(Circle, Square, Triangle);Kompilacja:
warning CS8509: Wyrażenie switch nie obsługuje wszystkich możliwych wartości typu wejściowego (nie jest wyczerpujące).
Na przykład nie jest uwzględniony wzorzec „Triangle”.I uruchomienie:
Circle { Radius = 1 }: 3,14
Square { Side = 2 }: 4,00
Unhandled exception. System.Runtime.CompilerServices.SwitchExpressionException: Non-exhaustive switch expression failed to match its input.
Unmatched value was Shape.Kompilator wie dokładnie, czego brakuje i buduje program. To jest ostrzeżenie
CS8509, nie błąd. W odcinku #1 i w poście do niego napisałem „błąd kompilacji, nie
runtime exception”. Na RC1 jest odwrotnie: kompilacja przechodzi, a wyjątek leci
w runtime, na pierwszym trójkącie. Co gorsza, komunikat wyjątku mówi „Shape”, nie
„Triangle” z samego logu nie dowiesz się, którego przypadku zabrakło.
Uczciwie trzeba dodać, co unia jednak zmienia: przy zwykłej hierarchii z gałęzią _ =>
kompilator milczy całkowicie. Przy unii zna nazwę brakującego przypadku. Decyzję,
czy to zatrzymuje build, zostawia jednak Tobie.
Trójkąt w unii, brak trójkąta w switch
Zasada:
kompilator C# rozróżnia „wiem, że to źle” od „nie pozwolę”.
Wyczerpującyswitchw C# 15 jest w pierwszej kategorii
– dopóki sam go nie przesuniesz do drugiej.
Jedna linijka, która robi z tego błąd
Program w jednym pliku (ten sam dotnet run app.cs, o którym był odcinek #1) przyjmuje właściwości MSBuild dyrektywą #:property na górze pliku:
#:property WarningsAsErrors=CS8509Z tą linijką ten sam kod kończy się tak:
error CS8509: Wyrażenie switch nie obsługuje wszystkich możliwych wartości typu wejściowego (nie jest wyczerpujące). Na przykład nie jest uwzględniony wzorzec „Triangle”.
Kompilacja nie powiodła się. Napraw błędy kompilacji i uruchom ją ponownie.W zwykłym projekcie to samo ustawiasz w .csproj: <WarningsAsErrors>CS8509</WarningsAsErrors>
w PropertyGroup. Jeśli zespół ma już <TreatWarningsAsErrors>true</TreatWarningsAsErrors>,
dostajesz to za darmo, razem z każdym innym ostrzeżeniem. Jeśli nie ma, CS8509 jest
pierwszym kandydatem, zanim w kodzie pojawi się pierwsza unia.
Zasada:
wybierz jedno ostrzeżenie, które na pewno oznacza błąd, i zrób z niego błąd.
CS8509 przy uniach to najtańsza taka decyzja w C# 15.
Etykietowany break – już bez flagi preview
Drugi temat z odcinka #1 też jest w RC1 i też nie wymaga preview. Przeszukujemy macierz 3 × 3 w poszukiwaniu piątki:
outer:
for (int i = 0; i < matrix.Length; i++)
{
for (int j = 0; j < matrix[i].Length; j++)
{
checkedCells++;
if (matrix[i][j] == target)
{
Console.WriteLine($"Znaleziono {target} w [{i}][{j}]");
break outer;
}
}
}Znaleziono 5 w [1][1]
Sprawdzone komorki: 5Pięć sprawdzonych komórek, nie dziewięć – break outer kończy obie pętle naraz, bez flagi bool sprawdzanej w warunku zewnętrznej pętli i bez goto. Nowa reguła stylu IDE0410 sama wskazuje w istniejącym kodzie miejsca, gdzie flagę albo goto da się zastąpić etykietą.
closed — zamknięte hierarchie, brat unii
Trzecia funkcja C# 15, której w odcinku #1 nie było. Słowo closed przed klasą (albo
rekordem) bazową mówi: dziedziczyć po mnie można tylko w tym samym projekcie:
public closed record Shape;
public record Circle(double Radius) : Shape;
public record Square(double Side) : Shape;Kompilator zna więc wszystkie przypadki i switch (ten sam co wyżej, bez gałęzi
domyślnej) jest dla niego wyczerpujący. Wynik identyczny jak przy unii. closed
jest niejawnie abstrakcyjne – nie połączysz go z sealed, static ani jawnymabstract. Jeśli zastanawiasz się, kiedy w ogóle sięgać po klasę bazową, a kiedy po
interfejs, zajrzyj do Klasa abstrakcyjna vs interfejs w C#.
Kiedy co?
Unia — gdy łączysz typy, które już istnieją i nie mają wspólnego przodka.closed — gdy projektujesz własną hierarchię od zera. Oba mają tę samą cechę przy
brakującym przypadku: CS8509, ostrzeżenie (sprawdzone na tym samym SDK — wyjątek z closed mówi przynajmniej Unmatched value was Square { Side = 2 }, bo rekord wypisuje swoją zawartość).
Zasada:
closedto „ta lista przypadków jest skończona” powiedziane kompilatorowi,
a nie komentarzowi w kodzie.
Otworzyłeś projekt — i cudzy kod już się wykonał
1 września 2026 Maarten Balliauw, od lat piszący o NuGecie i bezpieczeństwie .NET,
opublikował szczegółowy rozbiór: jak zbudować atak na łańcuch dostaw w .NET. Nie po to, żeby atakować — żeby pokazać, gdzie są drzwi. Cztery mechanizmy, które paczka NuGet może wykorzystać, dzielą się na dwie grupy.
Przy buildzie (i przy otwarciu projektu):
- MSBuild
.targetsz folderubuild/albobuildTransitive/paczki — MSBuild
dołącza go do Twojego projektu sam i może wykonać go przed kompilacją. - Generator źródeł — kod paczki uruchamiany w środku kompilatora.
Oba działają także w buildzie w tle, który IDE robi samo po otwarciu solution.
Nie uruchomiłeś programu, nie kliknąłeś „Build” — otworzyłeś projekt.
Przy starcie aplikacji:
- Inicjalizator modułu — rusza przy pierwszym użyciu biblioteki, przed Twoim kodem.
- Startup hook — zmienna
DOTNET_STARTUP_HOOKSładuje dowolną bibliotekę przedMain.
Autor pokazuje też wariant, który sprawdza zmienne środowiskowe typowe dla serwerów CI (CI, TF_BUILD) i uruchamia się wyłącznie tam — na laptopie programisty nie widać niczego.
Cztery drzwi dla kodu z paczki NuGet
Wybierz, co robisz z projektem, do którego ktoś dodał paczkę. Podświetlą się mechanizmy, które w tej chwili mogą uruchomić jej kod.
build/ paczki — MSBuild dołącza go samDOTNET_STARTUP_HOOKS — przed MainObrona, którą da się wdrożyć od ręki: plik blokady pakietów z RestorePackagesWithLockFile i tryb RestoreLockedMode na CI (restore nie może po cichu wziąć innej wersji), mapowanie źródeł pakietów w nuget.config (paczka o danej nazwie może przyjść tylko z Twojego feedu) i regularny przegląd zależności przechodnich. Sam autor mówi uczciwie: to nie daje pewności, tylko podnosi koszt ataku.
Zasada:
dodanie paczki NuGet to wpuszczenie cudzego kodu do procesu budowania,
nie tylko do aplikacji. Traktujdotnet add packagejak instalację programu.
Pułapka #2: NU3034 po zmianie certyfikatu Microsoftu
Od 23 września 2026 Microsoft podpisuje swoje paczki NuGet nowym certyfikatem.
Stare paczki zachowują stary podpis. Zmiana dotyczy Cię tylko wtedy, gdy w nuget.config masz listę zaufanych autorów (trustedSigners) albo sprawdzasz podpisy komendą dotnet nuget verify z odciskami certyfikatów. Jeśli tak, a nie dopiszesz nowego odcisku – instalacja nowych paczek Microsoftu kończy się błędem NU3034.
Poprawka to jedna komenda: dotnet nuget trust certificate Microsoft <odcisk>
–algorithm SHA256 z odciskiem z ogłoszenia Microsoftu (link w źródłach niżej).
Stare wpisy zostawiasz.
Uwaga:
ogłoszenie podaje wariant `dotnet nuget trust author … –algorithm SHA256`, ale na SDK 10.0.401 kończy się on błędem „nierozpoznany argument `–algorithm`” – `trust author` przyjmuje ścieżkę do paczki, nie odcisk. Wariant z `certificate` dopisuje do `nuget.config` dokładnie ten wpis `<author name=”Microsoft”>`, który pokazuje ogłoszenie (sprawdzone 01.10.2026).
I przypomnienie z odcinka #1: 1 listopada 2026 wygasają wszystkie stare klucze API
NuGet.org. Jeśli publikujesz paczki z pipeline’u, sprawdź to teraz, nie 31 października.
10 listopada: premiera .NET 11 i koniec .NET 8 i .NET 9
Tego samego dnia, kiedy wychodzi .NET 11, kończy się wsparcie .NET 8 i .NET 9 – obu naraz. .NET 8 to wersja LTS z listopada 2023 (trzy lata wsparcia). .NET 9 miał
krótkie wsparcie, które Microsoft wydłużył do 24 miesięcy — i dlatego oba kończą się
jednego dnia.
Aplikacje na .NET 8 i 9 dalej będą działać. Po 10 listopada nie dostaną jednak żadnej
poprawki bezpieczeństwa (Microsoft zastrzega tylko ewentualną ostatnią łatkę tego dnia,
jeśli wyjdzie krytyczny problem). Wrześniowe łatki z 8 września – .NET 10.0.12,
9.0.20 i 8.0.31 – należą do ostatnich dla ósemki i dziewiątki. Zalecenie Microsoftu:
.NET 10, wsparcie do listopada 2028.
Które terminy z tego odcinka dotyczą Ciebie?
Zaznacz, co pasuje do Twojej sytuacji. Lista niżej zostawi tylko Twoje daty — liczone od dzisiejszej.
Zasada:
„działa” i „jest wspierane” to dwie różne rzeczy. Po 10 listopada .NET 8 działa dokładnie tak samo – tylko każda nowa podatność zostaje w nim na zawsze.
GitHub Copilot: trzy zmiany, których nie włączałeś
W odcinku #1 był szok cenowy po przejściu Copilota na rozliczanie tokenów. We wrześniu ciąg dalszy – ceny bez zmian, ale trzy rzeczy zmieniają się same (changelog GitHub z 28 sierpnia):
- 28 września — code review Copilota ma nowy poziom domyślny: Balanced zamiast Lite. Mocniejszy model i cały kontekst repozytorium, a więc więcej zużytych kredytów. Chcesz starego zachowania – ustaw Lite jawnie.
- 28 września — czat na github.com i w GitHub Mobile połączony z agentem w chmurze. Historia rozmów jest trzymana przez całe życie konta, a nie jak dotąd 28 dni.
- 1 października — w planach Business i Enterprise opłata za stanowisko z góry,
zanim użytkownik dostanie dostęp.
Szybka runda
- C# 15:
with(...)w wyrażeniu kolekcji – pierwszy element podaje argumenty
konstruktora, np. porównywarkęStringComparer.OrdinalIgnoreCasedlaHashSet<string>. - C# 15: indeksery w rozszerzeniach – w bloku
extensiondopiszesz własnythis[int]do typu, którego nie jesteś właścicielem. - Visual Studio 18.10 – debuger podświetla w
ifz&&/||ten warunek, który
rozstrzygnął wynik, a „Attach to Process” widzi kontenery Podmana jak Dockera. - EF Core 11 –
dotnet ef database update NazwaMigracji --addtworzy migrację i od razu ją nakłada, jedną komendą.
Ściągawka — 8 newsów z września
| # | News | Konkret |
|---|---|---|
| 1 | .NET 11 RC1 | 8.09, go-live, C# 15 domyślny dla net11.0 |
| 2 | Unie w C# 15 | public union Shape(Circle, Square); — składnia inna niż w #1 |
| 3 | CS8509 | brak przypadku = ostrzeżenie; błąd tylko z WarningsAsErrors |
| 4 | break outer i closed | bez flagi preview; closed = hierarchia tylko w projekcie |
| 5 | Łańcuch dostaw | .targets i generatory działają już przy otwarciu projektu |
| 6 | NuGet | nowy certyfikat 23.09 (NU3034), stare klucze API wygasają 1.11 |
| 7 | 10 listopada | premiera .NET 11, koniec wsparcia .NET 8 i 9 |
| 8 | Copilot | 28.09 Balanced i historia na zawsze, 1.10 płatność z góry |
Zadanie na ten tydzień
Masz chwilę na eksperyment: pobierz .NET 11 RC1, zapisz kod z trójkątem jakoapp.cs i uruchom dotnet run app.cs. Przeczytaj CS8509 na własne oczy. Potem
celowo dopisz na górze #:property WarningsAsErrors=CS8509 i zobacz, jak ten sam kod przestaje się kompilować. Na koniec dopisz brakującą gałąź dla Triangle — i sprawdź, że ostrzeżenie znika.
Nie masz czasu: sprawdź, na jakim .NET stoją Twoje projekty (TargetFramework
w .csproj). Każdy na net8.0 albo net9.0 ma termin: 10 listopada.
Podsumowanie
- .NET 11 RC1 (8.09) ma licencję go-live; C# 15 jest w nim językiem domyślnym, bez flagi preview.
- Unia w C# 15 wylicza istniejące typy:
public union Shape(Circle, Square);. Do wartości sięgasz przezValue. - Niepełny
switchna unii to ostrzeżenie CS8509 i wyjątek w runtime — błędem staje się dopiero zWarningsAsErrors. - Paczka NuGet może wykonać kod przy samym otwarciu projektu (
.targets, generatory) — blokada wersji i mapowanie źródeł to minimum. - 10 listopada: premiera .NET 11 i koniec wsparcia .NET 8 i 9 tego samego dnia.
Pełny odcinek z animowanym przebiegiem tego, jak error zamienia się w warning, jest na kanale YouTube — w opisie są wszystkie źródła. Poprzednia partia newsów, z pierwszą (nieaktualną już) wersją składni unii: Newsy .NET — sierpień 2026.
🎓 Jeśli chcesz przejść C# od podstaw po poziom, na którym takie newsy od razu wiesz, gdzie przyłożyć – zacznij od darmowej roadmapy Junior .NET Developer
albo kursu Od Zera do .NET Developera.
Zobacz
- Switch w C# — od klasycznej instrukcji po pattern matching
- Class, struct czy record w C#? Kiedy używać którego typu
- Polimorfizm w C# — statyczny i dynamiczny, na przykładzie kolekcji
- Newsy .NET — C# 15, bomba w NuGet i szok cenowy Copilota (sierpień 2026)
Źródła:
.NET 11 RC1 ·
Co nowego w C# 15 ·
M. Balliauw — atak na łańcuch dostaw w .NET ·
Certyfikat NuGet Microsoftu ·
Koniec wsparcia .NET 8 i 9 ·
Copilot — changelog 28.08 ·
EF Core 11
🚀 Co dalej?
Zobacz to w praktyce na wideo i pobierz darmową roadmapę, żeby ułożyć naukę w spójną ścieżkę do pierwszej pracy.
- 🗺️ Pobierz darmową roadmapę Junior .NET Developer — 12 kroków od podstaw C# do pierwszej pracy: dev-hobby.pl
- 🎬 Subskrybuj kanał YouTube — nowe filmy co tydzień.
Zamień wiedzę w umiejętności
Pobierz darmową Roadmapę .NET i ułóż takie tematy jak ten w spójną ścieżkę do pierwszej pracy.
Pobieram roadmapę →