Samouczek: Eksploruj pomysły używając instrukcji najwyższego poziomu do tworzenia kodu podczas nauki
Z tego samouczka dowiesz się, jak wykonywać następujące działania:
- Poznaj reguły dotyczące korzystania z instrukcji najwyższego poziomu.
- Używanie instrukcji najwyższego poziomu do eksplorowania algorytmów.
- Przekształć eksploracje w komponenty wielokrotnego użytku.
Warunki wstępne
Musisz skonfigurować maszynę do uruchamiania platformy .NET 6 lub nowszej. Kompilator języka C# jest dostępny od wersji Visual Studio 2022 lub .NET 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 eksplorowanie
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 polecenia dotnet new console
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żny
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 dyrektyw global using
dla projektów, które używają następujących zestawów SDK:
- Microsoft.NET.Sdk
- Microsoft.NET.Sdk.Web
- Microsoft.NET.Sdk.Worker
Te niejawne dyrektywy global using
obejmują najbardziej typowe przestrzenie nazw dla typu projektu.
Aby uzyskać więcej informacji, zobacz artykuł dotyczący niejawnych dyrektyw using
Ta funkcja upraszcza eksplorację nowych pomysłów. Instrukcje najwyższego poziomu można używać do obsługi scenariuszy skryptów lub do eksplorowania. Gdy podstawy działają, możesz rozpocząć refaktoryzację kodu i tworzenie metod, klas lub innych modułów z utworzonych składników wielokrotnego użytku. Instrukcje najwyższego poziomu rzeczywiście umożliwiają szybkie eksperymentowanie i tworzenie poradników 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ą. Tworzysz funkcje 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 najwyższego poziomu kompilator rozpoznaje args
jako argumenty wiersza polecenia. Typ args jest string[]
, jak we wszystkich programach języka C#.
Kod można przetestować, uruchamiając następujące polecenie dotnet run
:
dotnet run -- Should I use top level statements in all my programs?
Argumenty po --
w wierszu polecenia są przekazywane do programu. Możesz zobaczyć typ zmiennej args
wydrukowanej 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świetla 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 10 odpowiedzi, które są twierdzące, pięć, które są niejednoznaczne, i pięć, które są negatywne. 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.
Kod do wygenerowania odpowiedzi zawiera deklarację zmiennej w instrukcjach najwyższego poziomu. Kompilator zawiera tę deklarację w metodzie Main
wygenerowanej przez kompilator. Ponieważ te deklaracje zmiennych są zmiennymi lokalnymi, nie można uwzględnić modyfikatora static
.
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 robiąc przerwy 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ć dyrektywę using
na początku pliku źródłowego:
using System.Threading.Tasks;
Dyrektywy using
powinny być umieszczone przed wszelkimi innymi oświadczeniami w pliku. W przeciwnym razie jest to błąd kompilatora. Możesz ponownie uruchomić program i zobaczyć animację. To zapewnia lepsze doświadczenie. 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 modyfikator async
i zwraca System.Threading.Tasks.Task. Ten program nie zwraca wartości, więc punkt wejścia programu zwraca Task
. 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ą wyrażenie await
, zwracany typ staje się System.Threading.Tasks.Task<TResult>.
Refaktoryzacja z myślą o przyszłości
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 głównej. Ten kod 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żna wyczyścić kod animacji w celu usunięcia niektórych duplikatów, używając pętli foreach
do iterowania zestawu elementów animacji zdefiniowanych w tablicy animations
.
Pełna metoda ShowConsoleAnimation
po refaktoryzacji powinna wyglądać podobnie do następującego kodu:
public static async Task ShowConsoleAnimation()
{
string[] animations = ["| -", "/ \\", "- |", "\\ /"];
for (int i = 0; i < 20; i++)
{
foreach (string s in animations)
{
Console.Write(s);
await Task.Delay(50);
Console.Write("\b\b\b");
}
}
Console.WriteLine();
}
Teraz masz kompletną aplikację i zrefaktoryzowałeś części wielokrotnego użytku do ponownego wykorzystania. Nową metodę narzędzia można wywołać z instrukcji najwyższego poziomu, jak pokazano 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.ShowConsoleAnimation
i dodano kolejną dyrektywę using
.
Streszczenie
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 różnych kawałkó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 konsoli. Te aplikacje obejmują 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#).