Udostępnij za pośrednictwem


Przewodnik po języku C#

Język C# jest najpopularniejszym językiem dla platformy .NET, bezpłatnego, międzyplatformowego środowiska deweloperskiego typu open source. Programy języka C# mogą być uruchamiane na wielu różnych urządzeniach, od urządzeń Internetu rzeczy (IoT) do chmury i wszędzie między nimi. Możesz pisać aplikacje dla telefonów, komputerów stacjonarnych i laptopów oraz serwerów.

C# to wieloplatformowy język ogólnego przeznaczenia, który sprawia, że deweloperzy są wydajni podczas pisania wysoce wydajnego kodu. W przypadku milionów deweloperów język C# jest najpopularniejszym językiem platformy .NET. Język C# ma szeroką obsługę ekosystemu i wszystkich obciążeń platformy .NET. W oparciu o zasady obiektowe zawiera wiele cech z innych paradygmatów, a nie tylko programowania funkcjonalnego. Funkcje niskiego poziomu obsługują scenariusze o wysokiej wydajności bez pisania niebezpiecznego kodu. Większość środowiska uruchomieniowego i bibliotek platformy .NET jest napisana w języku C#, a postęp w języku C# często przynosi korzyści wszystkim deweloperom platformy .NET.

Język C# znajduje się w rodzinie języków C. składni języka C# jest znana, jeśli używasz języków C, C++, JavaScript, TypeScript lub Java. Podobnie jak C i C++, średniki (;) definiują koniec instrukcji. W identyfikatorach języka C# uwzględniana jest wielkość liter. Język C# ma takie samo użycie nawiasów klamrowych, { i }, instrukcji sterujących, takich jak if, else i switch, oraz konstrukcji pętli, takich jak for i while. Język C# zawiera również instrukcję foreach dla dowolnego typu kolekcji.

Witaj świecie

Program "Hello, World" jest tradycyjnie używany do wprowadzenia języka programowania. W tym miejscu znajduje się on w języku C#:

// This line prints "Hello, World" 
Console.WriteLine("Hello, World");

Wiersz rozpoczynający się od // jest komentarzem jednoliniowym. Komentarze jednowierszowe języka C# zaczynają się od // i trwają do końca bieżącego wiersza. Język C# obsługuje również komentarze wielowierszowe. Komentarze wielowierszowe zaczynają się od /* i kończą na */. Metoda WriteLine klasy Console, która znajduje się w przestrzeni nazw System, generuje dane wyjściowe programu. Ta klasa jest dostarczana przez standardowe biblioteki klas, do których domyślnie są automatycznie odwoływały się w każdym programie języka C#. Inny formularz programu wymaga zadeklarowania klasy zawierającej i metody stanowiącej punkt wejścia programu. Kompilator syntetyzuje te elementy, gdy używasz instrukcji najwyższego poziomu.

Ten alternatywny format jest nadal prawidłowy i zawiera wiele podstawowych pojęć we wszystkich programach języka C#. Wiele istniejących przykładów w języku C# używa następującego równoważnego formatu:

using System;
namespace TourOfCsharp;

class Program
{
    static void Main()
    {
        // This line prints "Hello, World" 
        Console.WriteLine("Hello, World");
    }
}

Poprzedni program "Hello, World" rozpoczyna się od dyrektywy using odwołującej się do przestrzeni nazw System. Przestrzenie nazw zapewniają hierarchiczny sposób, dzięki któremu można organizować programy i biblioteki języka C#. Przestrzenie nazw zawierają typy i inne przestrzenie nazw — na przykład System przestrzeń nazw zawiera wiele typów, takich jak Console klasa, do których odwołuje się program, oraz wiele innych przestrzeni nazw, takich jak IO i Collections. Dyrektywa odwołująca using się do danej przestrzeni nazw umożliwia niekwalifikowane użycie typów będących członkami tej przestrzeni nazw. Ze względu na dyrektywę using program może użyć Console.WriteLine jako skrótu dla .System.Console.WriteLine We wcześniejszym przykładzie ta przestrzeń nazw została niejawnie dołączona.

Klasa Program zadeklarowana przez program "Hello, World" ma jeden element członkowski, metodę o nazwie Main. Metoda Main jest zadeklarowana za pomocą static modyfikatora. Chociaż metody wystąpień mogą odwoływać się do określonego otaczającego wystąpienia obiektu przy użyciu słowa kluczowego this, metody statyczne działają bez odwołania do określonego obiektu. Zgodnie z konwencją, gdy nie ma instrukcji najwyższego poziomu, metoda statyczna o nazwie Main służy jako punkt wejścia programu C#. Klasa zawierająca metodę Main jest zwykle nazwana Program.

Napiwek

Przykłady w tym artykule umożliwiają pierwsze przyjrzenie się kodowi języka C#. Niektóre przykłady mogą pokazywać elementy języka C#, których nie znasz. Gdy wszystko będzie gotowe do nauki języka C#, zacznij od naszych samouczków dla początkujących lub zapoznaj się z linkami w każdej sekcji. Jeśli masz doświadczenie w java, JavaScript, TypeScriptlub Python, przeczytaj nasze porady, aby uzyskać informacje potrzebne do szybkiego uczenia się języka C#.

Znane funkcje języka C#

Język C# jest przystępny dla początkujących, ale oferuje zaawansowane funkcje dla doświadczonych deweloperów piszących wyspecjalizowane aplikacje. Możesz szybko pracować wydajnie. Możesz dowiedzieć się więcej wyspecjalizowanych technik, ponieważ są one potrzebne dla aplikacji.

Aplikacje języka C# korzystają z automatycznego zarządzania pamięcią środowiska uruchomieniowego platformy .NET. Aplikacje języka C# używają również rozbudowanych bibliotek środowiska uruchomieniowego udostępnianych przez zestaw .NET SDK. Niektóre składniki są niezależne od platformy, takie jak biblioteki systemu plików, kolekcje danych i biblioteki matematyczne. Inne są specyficzne dla pojedynczego obciążenia, takiego jak biblioteki internetowe platformy ASP.NET Core lub biblioteka interfejsu użytkownika maui platformy .NET. Rozbudowany ekosystem open source w systemie NuGet rozszerza biblioteki będące częścią środowiska uruchomieniowego. Te biblioteki udostępniają jeszcze więcej składników, których można użyć.

C# to silnie typizowany język. Każda zadeklarowana zmienna ma typ znany w czasie kompilacji. Kompilator lub narzędzia edytorskie informują, czy też używasz tego typu niepoprawnie. Te błędy można naprawić, zanim kiedykolwiek uruchomisz program. Podstawowe typy danych są wbudowane w język i środowisko uruchomieniowe: typy wartości, takie jak , int, double, typy referencyjne, takie jak charstring, tablice i inne kolekcje. Podczas pisania programów tworzysz własne typy. Mogą to być struct typy wartości lub class typy definiujące zachowanie obiektowe. Można dodać modyfikator record do typów struct lub class, aby kompilator zsyntetyzował kod na potrzeby porównań równości. Można również utworzyć interface definicje, przedstawiające kontrakt lub zestaw członków, które musi zapewnić typ implementujący ten interfejs. Można również zdefiniować typy ogólne i metody. Typy generyczne używają parametrów typu, aby podać symbol zastępczy rzeczywistego typu podczas jego użycia.

Podczas pisania kodu definiujesz funkcje, zwane również metodami, które są elementami typów, takich jak struct i class. Te metody definiują zachowanie typów. Metody mogą być przeciążone, z różnymi liczbą lub typami parametrów. Metody mogą opcjonalnie zwracać wartość. Oprócz metod typy języka C# mogą mieć właściwości, które są elementami danych wspieranymi przez funkcje nazywane akcesorami. Typy języka C# mogą definiować zdarzenia, które umożliwiają typowi powiadamianie subskrybentów o ważnych akcjach. Język C# obsługuje techniki obiektowe, takie jak dziedziczenie i polimorfizm dla class typów.

Aplikacje języka C# używają wyjątków do raportowania i obsługi błędów. Ta praktyka jest znana, jeśli używasz języka C++ lub Java. Kod zgłasza wyjątek, gdy nie może wykonać zamierzonego działania. Inny fragment kodu, niezależnie od liczby poziomów w górę stosu wywołań, ma możliwość opcjonalnego odzyskania przy użyciu bloku try - catch.

Charakterystyczne funkcje języka C#

Niektóre elementy języka C# mogą być mniej znane.

Język C# zapewnia dopasowywanie wzorców. Te wyrażenia umożliwiają inspekcję danych i podejmowanie decyzji na podstawie ich cech. Dopasowywanie wzorca oferuje doskonałą składnię do kontrolowania przepływu na podstawie danych. Poniższy kod pokazuje, w jaki sposób metody operacji logicznych i, lub i xor mogą być wyrażane przy użyciu składni dopasowania wzorca.

public static bool Or(bool left, bool right) =>
    (left, right) switch
    {
        (true, true) => true,
        (true, false) => true,
        (false, true) => true,
        (false, false) => false,
    };

public static bool And(bool left, bool right) =>
    (left, right) switch
    {
        (true, true) => true,
        (true, false) => false,
        (false, true) => false,
        (false, false) => false,
    };
public static bool Xor(bool left, bool right) =>
    (left, right) switch
    {
        (true, true) => false,
        (true, false) => true,
        (false, true) => true,
        (false, false) => false,
    };

Wyrażenia dopasowywania wzorców można uprościć, używając _ jako mechanizmu obsługującego dowolną wartość. W poniższym przykładzie pokazano, jak można uprościć metodę i :

public static bool ReducedAnd(bool left, bool right) =>
    (left, right) switch
    {
        (true, true) => true,
        (_, _) => false,
    };

Powyższe przykłady deklarują również lekkie struktury danych w postaci krotek. krotka to uporządkowana sekwencja wartości o stałej długości z opcjonalnymi nazwami i indywidualnymi typami. Sekwencja jest ujęta w znaki ( i ). Deklaracja (left, right) definiuje krotkę z dwiema wartościami logicznymi: left i right. Każde ramię przełącznika deklaruje wartość krotki, taką jak (true, true). Krotki zapewniają wygodną składnię do deklarowania pojedynczego obiektu zawierającego wiele wartości.

Wyrażenia kolekcji dostarczają wspólną składnię dla wartości kolekcji. Wartości lub wyrażenia są zapisywane między znakami [ i ], a kompilator konwertuje to wyrażenie na wymagany typ kolekcji:

int[] numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
List<string> names = ["Alice", "Bob", "Charlie", "David"];

IEnumerable<int> moreNumbers = [.. numbers, 11, 12, 13];
IEnumerable<string> empty = [];

W poprzednim przykładzie przedstawiono różne typy kolekcji, które można zainicjować przy użyciu wyrażeń kolekcji. W jednym przykładzie wyrażenie [] pustej kolekcji jest używane do zadeklarowania pustej kolekcji. W innym przykładzie użyto elementu rozszerzającego .., aby rozwinąć kolekcję i dodać wszystkie jej wartości do wyrażenia kolekcji.

Aby pobrać jeden lub więcej elementów z kolekcji indeksowalnej, możesz użyć wyrażenia indeksu oraz wyrażenia zakresu .

string second = names[1]; // 0-based index
string last = names[^1]; // ^1 is the last element
int[] smallNumbers = numbers[0..5]; // 0 to 4

Indeks ^ wskazuje od końca, a nie od początku. Element ^0 znajduje się tuż za końcem kolekcji, więc ^1 jest ostatnim elementem. .. w wyrażeniu zakresu określa zakres elementów do uwzględnienia. Zakres zaczyna się od pierwszego indeksu i zawiera wszystkie elementy aż do, ale nie włącznie z, elementem na ostatnim indeksie.

Zapytanie zintegrowane z językiem (LINQ) udostępnia typową składnię opartą na wzorcu, która umożliwia wykonywanie zapytań lub przekształcanie dowolnej kolekcji danych. LINQ łączy składnię wykonywania zapytań dotyczących kolekcji w pamięci, danych strukturalnych, takich jak XML lub JSON, magazyn bazy danych, a nawet interfejsy API danych oparte na chmurze. Poznasz jeden zestaw składni i możesz wyszukiwać oraz manipulować danymi niezależnie od tego, gdzie są przechowywane. Następujące zapytanie znajduje wszystkich uczniów, których średnia punktu oceny jest większa niż 3,5:

var honorRoll = from student in Students
                where student.GPA > 3.5
                select student;

Powyższe zapytanie działa w przypadku wielu typów przechowywania reprezentowanych przez Students. Może to być kolekcja obiektów, tabela bazy danych, obiekt blob w magazynie chmurowym czy struktura XML. Ta sama składnia zapytania działa dla wszystkich typów przechowywania.

Model programowania asynchronicznego oparty na zadaniu umożliwia pisanie kodu, który odczytuje się tak, jakby był uruchamiany synchronicznie, mimo że jest uruchamiany asynchronicznie. Używa słów kluczowych async i await do opisywania metod, które są asynchroniczne, oraz gdy wyrażenie jest oceniane asynchronicznie. Poniższy przykład oczekuje na asynchroniczne żądanie internetowe. Po zakończeniu operacji asynchronicznej metoda zwraca długość odpowiedzi:

public static async Task<int> GetPageLengthAsync(string endpoint)
{
    var client = new HttpClient();
    var uri = new Uri(endpoint);
    byte[] content = await client.GetByteArrayAsync(uri);
    return content.Length;
}

Język C# obsługuje również instrukcję await foreach do iteracji kolekcji obsługiwanej przez operację asynchroniczną, na przykład API do stronicowania GraphQL. Poniższy przykład odczytuje dane we fragmentach, zwracając iterator, który zapewnia dostęp do każdego elementu, gdy jest dostępny:

public static async IAsyncEnumerable<int> ReadSequence()
{
    int index = 0;
    while (index < 100)
    {
        int[] nextChunk = await GetNextChunk(index);
        if (nextChunk.Length == 0)
        {
            yield break;
        }
        foreach (var item in nextChunk)
        {
            yield return item;
        }
        index++;
    }
}

Osoby wywołujące mogą iterować kolekcję przy użyciu instrukcji await foreach:

await foreach (var number in ReadSequence())
{
    Console.WriteLine(number);
}

Na koniec w ramach ekosystemu platformy .NET możesz używać programu Visual Studio lub Visual Studio Code z zestawem deweloperskim języka C#. Te narzędzia zapewniają bogatą wiedzę na temat języka C#, w tym pisanego kodu. Zapewniają one również możliwości debugowania.