Nazwa języka powstała analogicznie jak nazwa C++. Operator ++ w C (w C++ też) oznacza zwiększenie o jeden, więc C++ to więcej niż C. Autorzy C# wykorzystali podobny pomysł, gdzie symbol krzyżyka/kratki przypomina cztery połączone ze sobą operatory +. W muzyce dźwięk C♯ jest wyższy niż dźwięk C, może to sugerować, że język jest rozwinięciem C/C++[6].
Symbol ♯ (krzyżyk) jest niedostępny na większości klawiatur, niektórych czcionkach i przeglądarkach internetowych, dlatego zalecane jest używanie symbolu kratki (#), który bardzo przypomina symbol muzyczny. Czasami tam gdzie ma to uzasadnienie np. w materiałach promocyjnych, Microsoft używa nazwy C♯ zamiast C#[7].
obiektowość z hierarchią o jednym elemencie nadrzędnym: podobnie jak w Javie, kod programu jest zbiorem klas. W C#, podobnie jak w Javie/Object Pascalu, hierarchia dziedziczenia opiera się na istnieniu jednej klasy Object (System.Object), która stanowi element nadrzędny tej hierarchii. W szczególności oznacza to, że również typy proste (int, double, itd.) są strukturami z właściwymi sobie metodami, np. inti=1;strings=i.ToString();
odśmiecanie pamięci: zarządzaniem pamięcią zajmuje się środowisko uruchomieniowe. Oznacza to, że nie ma potrzeby samodzielnego zajmowania się zwalnianiem pamięci po obiektach, które przestają być używane
refleksje i atrybuty klas: w czasie pracy programu istnieje możliwość analizy struktury kodu z poziomu tego kodu. Umożliwia to tworzenie wysoce uniwersalnych mechanizmów operujących na strukturze kodu nieznanej w czasie kompilacji. Mechanizm ten wykorzystywany jest m.in. w bibliotekach ORM, narzędziach do analizy i weryfikacji kodu czy rozszerzeniach AOP. Mechanizm atrybutów został z C# zapożyczony do języka Java w wersji 1.5 (adnotacje), jakkolwiek samo Reflection API istniejące od pierwszego wydania języka stanowiło inspirację dla twórców C#
typy ogólne (generics – dostępne od wersji .NET 2.0): mechanizm zbliżony swoją ogólnością do szablonów w C++, jednak tu typ ogólny jest przenoszony do modułu binarnego i możliwy jest do wykorzystania bez konieczności posiadania kodu źródłowego
dynamiczne tworzenie kodu: biblioteki .NET umożliwiają dynamiczne tworzenie kodu w czasie działania programu i włączanie go do kodu aktualnie wykonywanego. Możliwe jest zarówno dynamiczne tworzenie kodu wykonywalnego ze źródeł C# jak i tworzenie dynamicznych modułów w języku pośrednim (CIL).
bogata biblioteka klas BCL, umożliwiająca rozwijanie aplikacji konsolowych, okienkowych (System.Windows.Forms oraz WPF od .NET Framework 3.0), bazodanowych (ADO.NET), sieciowych (System.Net), w architekturze rozproszonej (WebServices) czy dynamicznych aplikacji internetowych (ASP.NET) oraz dynamiczne treści multimedialne (Silverlight).
W C#, podobnie jak w C stosuje się dwa rodzaje komentarzy:
// to komentarz jednoliniowy, czyli wszystkiego, co znajduje się za nim, kompilator nie bierze pod uwagę.
Komentarz wielowierszowy zaczyna się od /* a kończy */. Kompilator nie bierze pod uwagę tego, co znajduje się pomiędzy.
Jeśli komentarz zaczyna się od /// lub /**, to jest to komentarz, w którym umieszcza się dokumentację do kodu.
Kopiec zaimplementowany przy pomocy szablonu klasy:
publicclassKopiec<T>{privateT[]tablica;// konstruktorpublicKopiec(T[]tablica){...}// wstawianie nowego elementu do kopcapublicvoidWstaw(Telem){...}}
słowo kluczowe yield.
typy częściowe – umożliwiają rozbicie klasy, struktury lub interfejsu do wielu plików źródłowych. Klasa częściowa wymaga użycia słowa kluczowego partial.
metody anonimowe – pozwalają na tworzenie funkcji „w miejscu”. Funkcje takie umożliwiają związanie kodu funkcji bezpośrednio z instancją delegata. Oznacza to, że te funkcje nie mają nazwy i mogą być wywołane jedynie przez wywołanie delegata.
typy Nullable – to typ prosty, który łączy wartości swojego typu podstawowego z dodatkowym oznaczeniem braku wartości (null). Typy te są tworzone przez połączenie nazwy typu prostego ze znakiem ‘?’ np. int?, float?. Głównym zastosowaniem tych typów jest współpraca z bazami danych. Reprezentują one wartości uzyskane z bazy danych, uwzględniając możliwość nie istnienia danej wartości w bazie.
C# 3.0
Słowa kluczowe "select, from, where" pozwalające na dostęp do SQL, XML, kolekcji i innych (Language integrated query (LINQ))
Proste inicjowanie obiektów: Klientk=newKlient();k.Imie="Jan"; staje się Klientk=newKlient(){Imie="Jan"};
wyrażenia lambda: listOfFoo.Where(delegate(Foox){returnx.size>10;}) staje się listOfFoo.Where(x=>x.size>10);
Typy domniemane: varx="hello"; oznacza to samo, co stringx="hello";
pattern matching - umożliwia sprawdzanie, czy zmienna jest danego typu i, jeśli tak, przypisanie tej wartości do nowej zmiennej typu docelowego. Możliwe jest również dołączanie dodatkowych warunków za pomocą słowa kluczowego when
intcount=5;stringlabel="Colors used in the map";varpair=(count,label);// zmienna pair będzie posiadać dwa elementy: pair.count oraz pair.label
C# 8.0
Jest obsługiwany przez środowisko Visual Studio 2019, a jego kompilator jest częścią platformy .NET Core 3.x[10][11].
Elementy członkowskie tylko do odczytu
Domyślne metody interfejsu
Ulepszenia dopasowania wzorca:
Przełączanie wyrażeń
Wzorce właściwości
Wzorce krotki
Wzorce pozycyjne
Używanie deklaracji
Statyczne funkcje lokalne
Indeksy i zakresy
varzdanie=newstring[]{// indeks od początku indeks od końca"Ala",// 0 ^7"ma",// 1 ^6"kota",// 2 ^5"a",// 3 ^4"kot",// 4 ^3"ma",// 5 ^2"Alę.",// 6 ^1};// 7 (lub words.Length) ^0Console.WriteLine($"Ostatnie słowo w zdaniu to {zdanie[^1]}");// program wypisze "Alę."
C# 9.0
Jest obsługiwany przez środowisko Visual Studio 2019, a jego kompilator jest częścią platformy .NET 5.0[12][13].
Jest obsługiwany przez środowisko Visual Studio 2022, a jego kompilator jest częścią platformy .NET 6.0[14][15]
Wprowadzono nową składnię - !! po nazwie parametru w sygnaturze metody sprawi, że zostanie sprawdzona wartość tego parametru i zostanie rzucony wyjątek, jeżeli jest ona nullem.
Wprowadzono global using, który umożliwia wszystkim plikom projektu dostęp do przestrzeni nazw określonych z tym dopiskiem.
Wprowadzono deklarację przestrzeni nazw o zakresie pliku.
Ulepszono wyrażenie lambda.
Rekordy mogą mieć zapieczętowane ToString.
Ciągi interpolowane jako stałe.
C# 11.0
Jest obsługiwany przez środowisko Visual Studio 2022, a jego kompilator jest częścią platformy .NET 7[16][17][18]
Dodanie atrybutów generycznych
Możliwość oznaczania właściwości i pól z użyciem modyfikatora required
Nowe linie w interpolacjach ciągów znaków
Aliasy dla IntPtr i UIntPtr
Rozszerzony zakres nameof
C# 12.0
Jest obsługiwany przez środowisko Visual Studio 2022, a jego kompilator jest częścią platformy .NET 8[19][20]
Prosty program napisany w języku C#. Po jego skompilowaniu i uruchomieniu wyświetlony zostanie napis "Podaj swoje imię: ". Po pobraniu imienia od użytkownika, zostanie ono wyświetlone w następnej linii.
usingSystem;publicclassPrzykladowaKlasa{publicstaticvoidMain(){Console.WriteLine("Podaj swoje imię:");stringimie=Console.ReadLine();Console.WriteLine($"Twoje imię to: {imie}");Console.WriteLine("Wciśnij dowolny klawisz by zakończyć program.");Console.ReadKey();}}
Inny program symulujący uniwersalną kostkę do gry, można w nim zobaczyć kilka podstawowych instrukcji języka C# oraz wykorzystanie funkcji instrukcji najwyższego poziomu.
intkostka;Randomliczba=new();stringinput=string.Empty;Console.Clear();while(true){Console.Write("Iluścienną kostką chcesz grać? ");try{kostka=int.Parse(Console.ReadLine());}catch{Console.WriteLine("Podano nieprawidłowe dane!");kostka=0;}if(kostka<4){Console.WriteLine("Kostka ma minimum 4 ściany.");}elsebreak;}Console.Clear();while(!input.Equals("q")){Console.WriteLine($"Wylosowana liczba to: {liczba.Next(kostka) + 1}\tAby zakończyć wciśnij Q + Enter");input=Console.ReadLine();}
Przykładowy program który działa jak stoper i aktualizuje się co sekundę:
usingSystem;usingSystem.Threading;classStopwatch{staticvoidMain(){intseconds=0;while(true){Console.Clear();// Wyczyść konsolę, aby zaktualizować czas na tym samym miejscuConsole.WriteLine("Czas: {0} sekund",seconds);Thread.Sleep(1000);// Poczekaj 1 sekundęseconds++;// Zwiększ licznik sekund o 1}}}