Självstudie: Utforska idéer med hjälp av toppnivåinstruktioner för att skapa kod när du lär dig

I den här självstudien får du lära dig att:

  • Lär dig reglerna som styr din användning av toppnivåinstruktioner.
  • Använd toppnivåinstruktioner för att utforska algoritmer.
  • Omstrukturera utforskningar till återanvändbara komponenter.

Förutsättningar

Du måste konfigurera datorn för att köra .NET 6, som innehåller kompilatorn C# 10. C# 10-kompilatorn är tillgänglig från och med Visual Studio 2022 eller .NET 6 SDK.

Den här självstudien förutsätter att du är bekant med C# och .NET, inklusive antingen Visual Studio eller .NET CLI.

Börja utforska

Med toppnivåinstruktioner kan du undvika den extra ceremoni som krävs genom att placera programmets startpunkt i en statisk metod i en klass. Den typiska startpunkten för ett nytt konsolprogram ser ut som följande kod:

using System;

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

Föregående kod är resultatet av att köra dotnet new console kommandot och skapa ett nytt konsolprogram. Dessa 11 rader innehåller bara en rad körbar kod. Du kan förenkla programmet med den nya funktionen för toppnivåinstruktioner. Det gör att du kan ta bort alla rader utom två i det här programmet:

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

Viktigt!

C#-mallarna för .NET 6 använder toppnivåinstruktioner. Programmet kanske inte matchar koden i den här artikeln om du redan har uppgraderat till .NET 6. Mer information finns i artikeln om nya C#-mallar som genererar instruktioner på toppnivå

.NET 6 SDK lägger också till en uppsättning implicitaglobal using direktiv för projekt som använder följande SDK:er:

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

Dessa implicita global using direktiv innehåller de vanligaste namnrymderna för projekttypen.

Mer information finns i artikeln om implicit användning av direktiv

Den här funktionen förenklar vad som behövs för att börja utforska nya idéer. Du kan använda instruktioner på den översta nivån för skriptscenarier eller utforska dem. När du har fått grunderna att fungera kan du börja omstrukturera koden och skapa metoder, klasser eller andra sammansättningar för återanvändbara komponenter som du har skapat. Toppnivåinstruktioner aktiverar självstudier för snabbexperiment och nybörjare. De ger också en smidig väg från experimentering till fullständiga program.

Toppnivåinstruktioner körs i den ordning de visas i filen. Toppnivåinstruktioner kan bara användas i en källfil i ditt program. Kompilatorn genererar ett fel om du använder dem i mer än en fil.

Skapa en magisk .NET-svarsdator

I den här självstudien ska vi skapa ett konsolprogram som svarar på en "ja" eller "nej"-fråga med ett slumpmässigt svar. Du kommer att bygga ut funktionerna steg för steg. Du kan fokusera på din uppgift snarare än ceremoni som behövs för strukturen för ett typiskt program. När du är nöjd med funktionerna kan du sedan omstrukturera programmet så som du vill.

En bra utgångspunkt är att skriva tillbaka frågan till konsolen. Du kan börja med att skriva följande kod:

Console.WriteLine(args);

Du deklarerar inte en args variabel. För den enda källfil som innehåller dina toppnivåinstruktioner args känner kompilatorn igen för att betyda kommandoradsargumenten. Typen av args är en string[], som i alla C#-program.

Du kan testa koden genom att köra följande dotnet run kommando:

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

Argumenten -- efter på kommandoraden skickas till programmet. Du kan se typen av args variabel eftersom det är det som skrivs ut i konsolen:

System.String[]

Om du vill skriva frågan till konsolen måste du räkna upp argumenten och separera dem med ett blanksteg. Ersätt anropet WriteLine med följande kod:

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

Nu när du kör programmet visas frågan korrekt som en sträng med argument.

Svara med ett slumpmässigt svar

När du har upprepat frågan kan du lägga till koden för att generera det slumpmässiga svaret. Börja med att lägga till en matris med möjliga svar:

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.",
];

Den här matrisen har tio svar som är jakande, fem som inte är bindande och fem som är negativa. Lägg sedan till följande kod för att generera och visa ett slumpmässigt svar från matrisen:

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

Du kan köra programmet igen för att se resultatet. Du bör se något som liknar följande utdata:

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.

Den här koden besvarar frågorna, men vi lägger till ytterligare en funktion. Du vill att din frågeapp ska simulera att du tänker på svaret. Du kan göra det genom att lägga till lite ASCII-animering och pausa när du arbetar. Lägg till följande kod efter raden som ekar frågan:

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();

Du måste också lägga till en using -instruktion överst i källfilen:

using System.Threading.Tasks;

Satserna using måste vara före andra instruktioner i filen. Annars är det ett kompilatorfel. Du kan köra programmet igen och se animeringen. Det gör en bättre upplevelse. Experimentera med längden på fördröjningen för att matcha din smak.

Föregående kod skapar en uppsättning snurrande rader avgränsade med ett blanksteg. Genom att lägga till nyckelordet await instrueras kompilatorn att generera programmets startpunkt som en metod som har async modifieraren och returnerar en System.Threading.Tasks.Task. Det här programmet returnerar inte något värde, så programmets startpunkt returnerar en Task. Om programmet returnerar ett heltalsvärde lägger du till en retursats i slutet av dina toppnivåinstruktioner. Den returnerade instruktionen skulle ange heltalsvärdet som ska returneras. Om dina toppnivåinstruktioner innehåller ett await uttryck blir System.Threading.Tasks.Task<TResult>returtypen .

Refaktorisering för framtiden

Programmet bör se ut som följande kod:

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]);

Föregående kod är rimlig. Det fungerar. Men det går inte att återanvända. Nu när programmet fungerar är det dags att hämta återanvändbara delar.

En kandidat är koden som visar den väntande animeringen. Det kodfragmentet kan bli en metod:

Du kan börja med att skapa en lokal funktion i filen. Ersätt den aktuella animeringen med följande kod:

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();
}

Föregående kod skapar en lokal funktion i huvudmetoden. Det går fortfarande inte att återanvända. Extrahera koden till en klass. Skapa en ny fil med namnet utilities.cs och lägg till följande 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();
        }
    }
}

En fil som har toppnivåinstruktioner kan också innehålla namnområden och typer i slutet av filen, efter de översta instruktionerna. Men i den här självstudien placerar du animeringsmetoden i en separat fil för att göra den enklare att återanvända.

Slutligen kan du rensa animeringskoden för att ta bort viss duplicering:

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

Nu har du ett komplett program och du har omstrukturerat återanvändbara delar för senare användning. Du kan anropa den nya verktygsmetoden från dina toppnivåinstruktioner enligt nedan i den färdiga versionen av huvudprogrammet:

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]);

Föregående exempel lägger till anropet till och lägger till Utilities.ShowConsoleAnimationytterligare using en instruktion.

Sammanfattning

Toppnivåinstruktioner gör det enklare att skapa enkla program som kan användas för att utforska nya algoritmer. Du kan experimentera med algoritmer genom att prova olika kodfragment. När du har lärt dig vad som fungerar kan du omstrukturera koden så att den blir mer underhållsbar.

Toppnivåinstruktioner förenklar program som baseras på konsolprogram. Dessa omfattar Azure-funktioner, GitHub-åtgärder och andra små verktyg. Mer information finns i Top-level statements (C#Programming Guide).