Share via


Tutorial: Explore ideias usando instruções de nível superior para criar código enquanto aprende

Neste tutorial, irá aprender a:

  • Conheça as regras que regem o uso de instruções de nível superior.
  • Use instruções de nível superior para explorar algoritmos.
  • Refatore explorações em componentes reutilizáveis.

Pré-requisitos

Você precisará configurar sua máquina para executar o .NET 6, que inclui o compilador C# 10. O compilador C# 10 está disponível a partir do Visual Studio 2022 ou do SDK do .NET 6.

Este tutorial pressupõe que você esteja familiarizado com C# e .NET, incluindo o Visual Studio ou a CLI do .NET.

Começar a explorar

As instruções de nível superior permitem que você evite a cerimônia extra exigida, colocando o ponto de entrada do seu programa em um método estático em uma classe. O ponto de partida típico para um novo aplicativo de console se parece com o seguinte código:

using System;

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

O código anterior é o resultado da execução do dotnet new console comando e da criação de um novo aplicativo de console. Essas 11 linhas contêm apenas uma linha de código executável. Você pode simplificar esse programa com o novo recurso de instruções de nível superior. Isso permite que você remova todas, exceto duas das linhas neste programa:

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

Importante

Os modelos C# para .NET 6 usam instruções de nível superior. Seu aplicativo pode não corresponder ao código neste artigo, se você já tiver atualizado para o .NET 6. Para obter mais informações, consulte o artigo sobre Novos modelos C# geram instruções de nível superior

O SDK do .NET 6 também adiciona um conjunto de diretivas implícitasglobal using para projetos que usam os seguintes SDKs:

  • Microsoft.NET.Sdk
  • Microsoft.NET.Sdk.Web
  • Microsoft.NET.Sdk.Trabalhador

Essas diretivas implícitas global using incluem os namespaces mais comuns para o tipo de projeto.

Para obter mais informações, consulte o artigo sobre Uso implícito de diretivas

Este recurso simplifica o que é necessário para começar a explorar novas ideias. Você pode usar instruções de nível superior para cenários de script ou para explorar. Depois de ter o básico funcionando, você pode começar a refatorar o código e criar métodos, classes ou outros assemblies para componentes reutilizáveis que você criou. Instruções de nível superior permitem experimentação rápida e tutoriais para iniciantes. Eles também fornecem um caminho suave da experimentação para programas completos.

As instruções de nível superior são executadas na ordem em que aparecem no arquivo. As instruções de nível superior só podem ser usadas em um arquivo de origem em seu aplicativo. O compilador gera um erro se você usá-los em mais de um arquivo.

Crie uma máquina de resposta .NET mágica

Para este tutorial, vamos criar um aplicativo de console que responda a uma pergunta "sim" ou "não" com uma resposta aleatória. Você criará a funcionalidade passo a passo. Você pode se concentrar em sua tarefa em vez de cerimônia necessária para a estrutura de um programa típico. Então, quando estiver satisfeito com a funcionalidade, você pode refatorar o aplicativo como achar melhor.

Um bom ponto de partida é escrever a pergunta de volta para o console. Você pode começar escrevendo o seguinte código:

Console.WriteLine(args);

Você não declara uma args variável. Para o único arquivo de origem que contém suas instruções de nível superior, o compilador reconhece args que significa os argumentos de linha de comando. O tipo de args é um string[], como em todos os programas C#.

Você pode testar seu código executando o seguinte dotnet run comando:

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

Os argumentos após o -- na linha de comando são passados para o programa. Você pode ver o args tipo da variável, porque é isso que está impresso no console:

System.String[]

Para escrever a pergunta no console, você precisará enumerar os argumentos e separá-los com um espaço. Substitua a WriteLine chamada pelo seguinte código:

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

Agora, quando você executa o programa, ele exibirá corretamente a pergunta como uma sequência de argumentos.

Responda com uma resposta aleatória

Depois de ecoar a pergunta, você pode adicionar o código para gerar a resposta aleatória. Comece adicionando uma série de respostas possíveis:

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

Esta matriz tem dez respostas afirmativas, cinco sem compromisso e cinco negativas. Em seguida, adicione o seguinte código para gerar e exibir uma resposta aleatória da matriz:

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

Você pode executar o aplicativo novamente para ver os resultados. Você deve ver algo como a seguinte saída:

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.

Este código responde às perguntas, mas vamos adicionar mais um recurso. Você gostaria que seu aplicativo de perguntas simulasse pensar na resposta. Você pode fazer isso adicionando um pouco de animação ASCII e pausando enquanto trabalha. Adicione o seguinte código após a linha que ecoa a pergunta:

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

Você também precisará adicionar uma using instrução à parte superior do arquivo de origem:

using System.Threading.Tasks;

As using declarações devem ser anteriores a quaisquer outras declarações constantes dos autos. Caso contrário, é um erro do compilador. Você pode executar o programa novamente e ver a animação. Isso torna a experiência melhor. Experimente a duração do atraso para corresponder ao seu gosto.

O código anterior cria um conjunto de linhas giratórias separadas por um espaço. Adicionar a palavra-chave instrui o compilador a await gerar o ponto de entrada do programa como um método que tem o async modificador e retorna um System.Threading.Tasks.Taskarquivo . Este programa não retorna um valor, portanto, o ponto de entrada do programa retorna um Taskarquivo . Se o programa retornar um valor inteiro, você adicionará uma instrução return ao final das instruções de nível superior. Essa instrução return especificaria o valor inteiro a ser retornado. Se suas instruções de nível superior incluírem uma await expressão, o tipo de retorno se tornará System.Threading.Tasks.Task<TResult>.

Refatoração para o futuro

Seu programa deve se parecer com o seguinte código:

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

O código anterior é razoável. Está a funcionar. Mas não é reutilizável. Agora que você tem o aplicativo funcionando, é hora de retirar as peças reutilizáveis.

Um candidato é o código que exibe a animação em espera. Esse trecho pode se tornar um método:

Você pode começar criando uma função local em seu arquivo. Substitua a animação atual pelo seguinte código:

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

O código anterior cria uma função local dentro do seu método principal. Isso ainda não é reutilizável. Então, extraia esse código em uma classe. Crie um novo arquivo chamado utilities.cs e adicione o seguinte código:

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

Um arquivo que tem instruções de nível superior também pode conter namespaces e tipos no final do arquivo, após as instruções de nível superior. Mas para este tutorial, você coloca o método de animação em um arquivo separado para torná-lo mais facilmente reutilizável.

Finalmente, você pode limpar o código de animação para remover alguma duplicação:

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

Agora você tem uma aplicação completa e refatorou as peças reutilizáveis para uso posterior. Você pode chamar o novo método de utilidade a partir de suas instruções de nível superior, como mostrado abaixo na versão concluída do programa principal:

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

O exemplo anterior adiciona a chamada a Utilities.ShowConsoleAnimation, e adiciona uma instrução adicional using .

Resumo

Instruções de nível superior facilitam a criação de programas simples para uso para explorar novos algoritmos. Você pode experimentar algoritmos experimentando diferentes trechos de código. Depois de aprender o que funciona, você pode refatorar o código para ser mais fácil de manter.

As instruções de nível superior simplificam os programas baseados em aplicativos de console. Isso inclui funções do Azure, ações do GitHub e outros pequenos utilitários. Para obter mais informações, consulte Instruções de nível superior (Guia de programação em C#).