Samouczek: eksplorowanie pomysłów przy użyciu instrukcji najwyższego poziomu do kompilowania kodu podczas nauki

Z tego samouczka dowiesz się, jak wykonywać następujące czynności:

  • Poznaj reguły dotyczące korzystania z instrukcji najwyższego poziomu.
  • Używanie instrukcji najwyższego poziomu do eksplorowania algorytmów.
  • Refaktoryzacja eksploracji składników wielokrotnego użytku.

Wymagania wstępne

Musisz skonfigurować maszynę do uruchamiania platformy .NET 6, która obejmuje kompilator języka C# 10. Kompilator języka C# 10 jest dostępny od wersji Visual Studio 2022 lub .NET 6 SDK.

W tym samouczku założono, że znasz języki C# i .NET, w tym program Visual Studio lub interfejs wiersza polecenia platformy .NET.

Rozpocznij eksplorację

Instrukcje najwyższego poziomu umożliwiają uniknięcie dodatkowej ceremonii wymaganej przez umieszczenie punktu wejścia programu w metodzie statycznej w klasie. Typowy punkt wyjścia dla nowej aplikacji konsolowej wygląda następująco:

using System;

namespace Application
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Hello World!");
        }
    }
}

Powyższy kod jest wynikiem uruchomienia dotnet new console polecenia i utworzenia nowej aplikacji konsolowej. Te 11 wierszy zawierają tylko jeden wiersz kodu wykonywalnego. Ten program można uprościć za pomocą nowej funkcji instrukcji najwyższego poziomu. Umożliwia to usunięcie wszystkich, ale dwóch wierszy w tym programie:

// See https://aka.ms/new-console-template for more information
Console.WriteLine("Hello, World!");

Ważne

Szablony języka C# dla platformy .NET 6 używają instrukcji najwyższego poziomu. Aplikacja może nie być zgodna z kodem w tym artykule, jeśli został już uaktualniony do platformy .NET 6. Aby uzyskać więcej informacji, zobacz artykuł dotyczący nowych szablonów języka C# generowania instrukcji najwyższego poziomu

Zestaw SDK platformy .NET 6 dodaje również zestaw niejawnych global using dyrektyw dla projektów korzystających z następujących zestawów SDK:

  • Microsoft.NET.Sdk
  • Microsoft.NET.Sdk.Web
  • Microsoft.NET.Sdk.Worker

Te niejawne global using dyrektywy obejmują najbardziej typowe przestrzenie nazw dla typu projektu.

Aby uzyskać więcej informacji, zobacz artykuł dotyczący niejawnych dyrektyw using

Ta funkcja upraszcza to, co jest potrzebne do rozpoczęcia eksplorowania nowych pomysłów. Instrukcje najwyższego poziomu można używać do obsługi scenariuszy skryptów lub do eksplorowania. Po zakończeniu pracy z podstawami możesz rozpocząć refaktoryzację kodu i utworzyć metody, klasy lub inne zestawy dla utworzonych składników wielokrotnego użytku. Instrukcje najwyższego poziomu umożliwiają szybkie eksperymentowanie i samouczki dla początkujących. Zapewniają one również płynną ścieżkę od eksperymentowania do pełnych programów.

Instrukcje najwyższego poziomu są wykonywane w kolejności, w której są wyświetlane w pliku. Instrukcje najwyższego poziomu mogą być używane tylko w jednym pliku źródłowym w aplikacji. Kompilator generuje błąd, jeśli używasz ich w więcej niż jednym pliku.

Tworzenie magicznej maszyny odpowiedzi platformy .NET

W tym samouczku skompilujmy aplikację konsolową, która odpowiada na pytanie "tak" lub "nie" z losową odpowiedzią. Utworzysz funkcjonalność krok po kroku. Możesz skupić się na zadaniu, a nie na ceremonii potrzebnej do struktury typowego programu. Następnie, gdy będziesz zadowolony z funkcji, możesz refaktoryzować aplikację zgodnie z potrzebami.

Dobrym punktem wyjścia jest napisanie pytania z powrotem do konsoli. Możesz zacząć od napisania następującego kodu:

Console.WriteLine(args);

Nie deklarujesz zmiennej args . W przypadku pojedynczego pliku źródłowego zawierającego instrukcje args najwyższego poziomu kompilator rozpoznaje argumenty wiersza polecenia. Typ args to string[], jak we wszystkich programach języka C#.

Kod można przetestować, uruchamiając następujące dotnet run polecenie:

dotnet run -- Should I use top level statements in all my programs?

Argumenty po -- wierszu polecenia są przekazywane do programu. Możesz zobaczyć typ zmiennej args , ponieważ jest to, co jest drukowane w konsoli:

System.String[]

Aby napisać pytanie w konsoli, należy wyliczyć argumenty i oddzielić je spacją. Zastąp wywołanie WriteLine następującym kodem:

Console.WriteLine();
foreach(var s in args)
{
    Console.Write(s);
    Console.Write(' ');
}
Console.WriteLine();

Teraz po uruchomieniu programu poprawnie wyświetli ono pytanie jako ciąg argumentów.

Odpowiadanie przy użyciu odpowiedzi losowej

Po powtórzeniu pytania możesz dodać kod, aby wygenerować losową odpowiedź. Zacznij od dodania tablicy możliwych odpowiedzi:

string[] answers =
[
    "It is certain.",       "Reply hazy, try again.",     "Don’t count on it.",
    "It is decidedly so.",  "Ask again later.",           "My reply is no.",
    "Without a doubt.",     "Better not tell you now.",   "My sources say no.",
    "Yes – definitely.",    "Cannot predict now.",        "Outlook not so good.",
    "You may rely on it.",  "Concentrate and ask again.", "Very doubtful.",
    "As I see it, yes.",
    "Most likely.",
    "Outlook good.",
    "Yes.",
    "Signs point to yes.",
];

Ta tablica zawiera dziesięć odpowiedzi, które są twierdzące, pięć, które nie są zatwierdzające, i pięć, które są ujemne. Następnie dodaj następujący kod, aby wygenerować i wyświetlić losową odpowiedź z tablicy:

var index = new Random().Next(answers.Length - 1);
Console.WriteLine(answers[index]);

Możesz ponownie uruchomić aplikację, aby wyświetlić wyniki. Powinny zostać wyświetlone dane wyjściowe podobne do następujących:

dotnet run -- Should I use top level statements in all my programs?

Should I use top level statements in all my programs?
Better not tell you now.

Ten kod odpowiada na pytania, ale dodajmy jeszcze jedną funkcję. Chcesz, aby aplikacja pytań symulowała myślenie o odpowiedzi. Możesz to zrobić, dodając trochę animacji ASCII i wstrzymując podczas pracy. Dodaj następujący kod po wierszu, który odzwierciedla pytanie:

for (int i = 0; i < 20; i++)
{
    Console.Write("| -");
    await Task.Delay(50);
    Console.Write("\b\b\b");
    Console.Write("/ \\");
    await Task.Delay(50);
    Console.Write("\b\b\b");
    Console.Write("- |");
    await Task.Delay(50);
    Console.Write("\b\b\b");
    Console.Write("\\ /");
    await Task.Delay(50);
    Console.Write("\b\b\b");
}
Console.WriteLine();

Należy również dodać instrukcję using na początku pliku źródłowego:

using System.Threading.Tasks;

Instrukcje using muszą być przed wszelkimi innymi instrukcjami w pliku. W przeciwnym razie jest to błąd kompilatora. Możesz ponownie uruchomić program i zobaczyć animację. To sprawia, że lepsze środowisko. Poeksperymentuj z długością opóźnienia, aby dopasować smak.

Powyższy kod tworzy zestaw wirujących wierszy oddzielonych spacją. Dodanie słowa kluczowego await powoduje, że kompilator wygeneruje punkt wejścia programu jako metodę, która ma async modyfikator, i zwraca element System.Threading.Tasks.Task. Ten program nie zwraca wartości, więc punkt wejścia programu zwraca Taskwartość . Jeśli program zwraca wartość całkowitą, należy dodać instrukcję return na końcu instrukcji najwyższego poziomu. Ta instrukcja return określa wartość całkowitą, która ma być zwracana. Jeśli instrukcje najwyższego poziomu zawierają await wyrażenie, zwracany typ stanie się System.Threading.Tasks.Task<TResult>.

Refaktoryzacja na przyszłość

Twój program powinien wyglądać podobnie do następującego kodu:

Console.WriteLine();
foreach(var s in args)
{
    Console.Write(s);
    Console.Write(' ');
}
Console.WriteLine();

for (int i = 0; i < 20; i++)
{
    Console.Write("| -");
    await Task.Delay(50);
    Console.Write("\b\b\b");
    Console.Write("/ \\");
    await Task.Delay(50);
    Console.Write("\b\b\b");
    Console.Write("- |");
    await Task.Delay(50);
    Console.Write("\b\b\b");
    Console.Write("\\ /");
    await Task.Delay(50);
    Console.Write("\b\b\b");
}
Console.WriteLine();

string[] answers =
[
    "It is certain.",       "Reply hazy, try again.",     "Don't count on it.",
    "It is decidedly so.",  "Ask again later.",           "My reply is no.",
    "Without a doubt.",     "Better not tell you now.",   "My sources say no.",
    "Yes – definitely.",    "Cannot predict now.",        "Outlook not so good.",
    "You may rely on it.",  "Concentrate and ask again.", "Very doubtful.",
    "As I see it, yes.",
    "Most likely.",
    "Outlook good.",
    "Yes.",
    "Signs point to yes.",
];

var index = new Random().Next(answers.Length - 1);
Console.WriteLine(answers[index]);

Powyższy kod jest rozsądny. To działa. Ale nie jest wielokrotnego użytku. Teraz, gdy aplikacja działa, nadszedł czas, aby ściągnąć części wielokrotnego użytku.

Jednym z kandydatów jest kod, który wyświetla animację oczekiwania. Ten fragment kodu może stać się metodą:

Możesz zacząć od utworzenia funkcji lokalnej w pliku. Zastąp bieżącą animację następującym kodem:

await ShowConsoleAnimation();

static async Task ShowConsoleAnimation()
{
    for (int i = 0; i < 20; i++)
    {
        Console.Write("| -");
        await Task.Delay(50);
        Console.Write("\b\b\b");
        Console.Write("/ \\");
        await Task.Delay(50);
        Console.Write("\b\b\b");
        Console.Write("- |");
        await Task.Delay(50);
        Console.Write("\b\b\b");
        Console.Write("\\ /");
        await Task.Delay(50);
        Console.Write("\b\b\b");
    }
    Console.WriteLine();
}

Powyższy kod tworzy funkcję lokalną wewnątrz metody main. To nadal nie jest wielokrotnego użytku. Dlatego wyodrębnij ten kod do klasy. Utwórz nowy plik o nazwie utilities.cs i dodaj następujący kod:

namespace MyNamespace
{
    public static class Utilities
    {
        public static async Task ShowConsoleAnimation()
        {
            for (int i = 0; i < 20; i++)
            {
                Console.Write("| -");
                await Task.Delay(50);
                Console.Write("\b\b\b");
                Console.Write("/ \\");
                await Task.Delay(50);
                Console.Write("\b\b\b");
                Console.Write("- |");
                await Task.Delay(50);
                Console.Write("\b\b\b");
                Console.Write("\\ /");
                await Task.Delay(50);
                Console.Write("\b\b\b");
            }
            Console.WriteLine();
        }
    }
}

Plik zawierający instrukcje najwyższego poziomu może również zawierać przestrzenie nazw i typy na końcu pliku po instrukcjach najwyższego poziomu. Jednak na potrzeby tego samouczka metoda animacji zostanie umieszczona w osobnym pliku, aby ułatwić jej wielokrotne użycie.

Na koniec możesz wyczyścić kod animacji, aby usunąć pewne duplikaty:

foreach (string s in animations)
{
    Console.Write(s);
    await Task.Delay(50);
    Console.Write("\b\b\b");
}

Teraz masz kompletną aplikację i refaktoryzujesz części wielokrotnego użytku do późniejszego użycia. Nową metodę narzędzia można wywołać z instrukcji najwyższego poziomu, jak pokazano poniżej w gotowej wersji głównego programu:

using MyNamespace;

Console.WriteLine();
foreach(var s in args)
{
    Console.Write(s);
    Console.Write(' ');
}
Console.WriteLine();

await Utilities.ShowConsoleAnimation();

string[] answers =
[
    "It is certain.",       "Reply hazy, try again.",     "Don’t count on it.",
    "It is decidedly so.",  "Ask again later.",           "My reply is no.",
    "Without a doubt.",     "Better not tell you now.",   "My sources say no.",
    "Yes – definitely.",    "Cannot predict now.",        "Outlook not so good.",
    "You may rely on it.",  "Concentrate and ask again.", "Very doubtful.",
    "As I see it, yes.",
    "Most likely.",
    "Outlook good.",
    "Yes.",
    "Signs point to yes.",
];

var index = new Random().Next(answers.Length - 1);
Console.WriteLine(answers[index]);

W poprzednim przykładzie dodano wywołanie metody Utilities.ShowConsoleAnimationi dodano dodatkową using instrukcję .

Podsumowanie

Instrukcje najwyższego poziomu ułatwiają tworzenie prostych programów do użycia w celu eksplorowania nowych algorytmów. Możesz eksperymentować z algorytmami, próbując próbować różnych fragmentów kodu. Gdy już wiesz, co działa, możesz refaktoryzować kod, aby był bardziej konserwowalny.

Instrukcje najwyższego poziomu upraszczają programy oparte na aplikacjach konsolowych. Obejmują one funkcje platformy Azure, akcje GitHub i inne małe narzędzia. Aby uzyskać więcej informacji, zobacz Instrukcje najwyższego poziomu (Przewodnik programowania w języku C#).