Учебное пособие: Исследуйте идеи, используя операторы верхнего уровня для создания кода по мере обучения
В этом руководстве описано, как:
- Изучите правила, регулирующие использование операторов верхнего уровня.
- Используйте инструкции верхнего уровня для изучения алгоритмов.
- Преобразование исследований в компоненты для повторного использования.
Необходимые условия
Необходимо настроить компьютер для запуска .NET 6 или более поздней версии. Компилятор C# доступен начиная с Visual Studio 2022 или пакета SDK для .NET.
В этом руководстве предполагается, что вы знакомы с C# и .NET, включая Visual Studio или .NET CLI.
Начало изучения
Инструкции топ-уровня позволяют избежать дополнительной обработки, которая возникает при необходимости размещения точки входа программы в статический метод в классе. Типичный начальный пункт для нового консольного приложения выглядит следующим образом:
using System;
namespace Application
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Hello World!");
}
}
}
Приведенный выше код является результатом выполнения команды dotnet new console
и создания консольного приложения. Эти 11 строки содержат только одну строку исполняемого кода. Эту программу можно упростить с помощью новой функции инструкций верхнего уровня. Это позволяет удалить все, кроме двух строк в этой программе:
// See https://aka.ms/new-console-template for more information
Console.WriteLine("Hello, World!");
Важный
Шаблоны C# для .NET 6 используют инструкции верхнего уровня . Приложение может не соответствовать коду в этой статье, если вы уже обновили его до .NET 6. Дополнительные сведения см. в статье о новых шаблонах C#, которые создают инструкции на верхнем уровне
Пакет SDK для .NET 6 также добавляет набор неявных директив
- Microsoft.NET.Sdk
- Microsoft.NET.Sdk.Web
- Microsoft.NET.Sdk.Worker
Эти неявные директивы global using
включают наиболее распространенные пространства имен для типа проекта.
Дополнительные сведения см. в статье о неявных директив using
Эта функция упрощает изучение новых идей. Инструкции верхнего уровня можно использовать для сценариев скриптов или для исследований. После работы с основами можно начать рефакторинг кода и создать методы, классы или другие сборки для созданных повторно используемых компонентов. Инструкции верхнего уровня позволяют быстро экспериментировать и учебные пособия для начинающих. Они также обеспечивают гладкий путь от экспериментирования до полных программ.
Инструкции верхнего уровня выполняются в том порядке, в котором они отображаются в файле. Инструкции верхнего уровня можно использовать только в одном исходном файле в приложении. Компилятор создает ошибку, если они используются в нескольких файлах.
Создание волшебного компьютера ответов .NET
В этом руководстве мы создадим консольное приложение, которое отвечает на вопрос "да" или "нет" с случайным ответом. Вы строите функциональность шаг за шагом. Вы можете сосредоточиться на задаче, а не на церемонии, необходимой для структуры типичной программы. Затем, когда вы удовлетворены функциональностью, вы можете отрефакторить приложение по своему усмотрению.
Хорошая отправная точка — написать вопрос обратно в консоль. Для начала можно написать следующий код:
Console.WriteLine(args);
Вы не объявляете переменную args
. Для одного исходного файла, содержащего инструкции верхнего уровня, компилятор распознает args
, чтобы означать аргументы командной строки. Тип args — это string[]
, как и во всех программах C#.
Чтобы протестировать код, выполните следующую команду dotnet run
:
dotnet run -- Should I use top level statements in all my programs?
Аргументы после --
в командной строке передаются программе. Вы можете увидеть тип переменной args
, выведенный на консоль.
System.String[]
Чтобы написать вопрос в консоль, необходимо перечислить аргументы и разделить их пробелом. Замените вызов WriteLine
следующим кодом:
Console.WriteLine();
foreach(var s in args)
{
Console.Write(s);
Console.Write(' ');
}
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.",
];
Этот массив содержит 10 утвердительных ответов, пять нейтральных и пять отрицательных. Затем добавьте следующий код, чтобы создать и отобразить случайный ответ из массива:
var index = new Random().Next(answers.Length - 1);
Console.WriteLine(answers[index]);
Вы можете снова запустить приложение, чтобы просмотреть результаты. Вы должны увидеть примерно следующее выходные данные:
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.
Код для создания ответа включает объявление переменной в инструкциях верхнего уровня. Компилятор включает это объявление в созданный компилятором метод Main
. Так как эти объявления переменных являются локальными переменными, нельзя включить модификатор static
.
Этот код отвечает на вопросы, но добавим еще одну функцию. Вы хотите, чтобы ваше приложение вопросов имитировало мышление об ответе. Это можно сделать, добавив немного анимации ASCII и делая паузы во время работы. Добавьте следующий код после строки, которая отражает вопрос:
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();
Кроме того, необходимо добавить директиву using
в начало исходного файла:
using System.Threading.Tasks;
Директивы using
должны быть перед любыми другими инструкциями в файле. В противном случае это ошибка компилятора. Вы можете снова запустить программу и увидеть анимацию. Это улучшает опыт. Поэкспериментируйте с длиной задержки, чтобы соответствовать вашему вкусу.
Предыдущий код создает набор вращающихся линий, отделенных друг от друга пробелами. Добавление ключевого слова await
указывает компилятору создать точку входа программы в качестве метода с модификатором async
и возвращает System.Threading.Tasks.Task. Эта программа не возвращает значение, поэтому точка входа программы возвращает Task
. Если программа возвращает целочисленное значение, вы добавите оператор return в конец инструкций верхнего уровня. Этот оператор возврата укажет целочисленное значение, которое следует вернуть. Если в операторах верхнего уровня присутствует выражение await
, возвращаемый тип становится System.Threading.Tasks.Task<TResult>.
Рефакторинг для будущего
Программа должна выглядеть следующим образом:
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]);
Приведенный выше код является разумным. Оно работает. Но это не допускает повторного использования. Теперь, когда приложение у вас работает, пришло время извлечь повторно используемые части.
Одним из кандидатов является код, отображающий анимацию ожидания. Этот фрагмент кода может стать методом:
Сначала можно создать локальную функцию в файле. Замените текущую анимацию следующим кодом:
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();
}
Предыдущий код создает локальную функцию внутри основного метода. Этот код по-прежнему не используется повторно. Извлеките этот код в класс. Создайте файл с именем utilities.cs и добавьте следующий код:
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();
}
}
}
Файл с операторами верхнего уровня также может содержать пространства имен и типы в конце файла после инструкций верхнего уровня. Но для этого руководства вы помещаете метод анимации в отдельный файл, чтобы сделать его более легко используемым повторно.
Наконец, можно очистить код анимации, чтобы удалить некоторые дублирования, используя цикл foreach
для итерации с помощью набора элементов анимации, определенных в массиве animations
.
Полный метод ShowConsoleAnimation
после рефакторинга должен выглядеть следующим образом:
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();
}
Теперь у вас есть полное приложение, и вы рефакторизовали повторно используемые части для последующего использования. Вы можете вызвать новый метод служебной программы из инструкций верхнего уровня, как показано в готовой версии основной программы:
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]);
В предыдущем примере добавляется вызов Utilities.ShowConsoleAnimation
и добавляется ещё одна директива using
.
Сводка
Инструкции верхнего уровня упрощают создание простых программ для изучения новых алгоритмов. Вы можете поэкспериментировать с алгоритмами, пробуя различные фрагменты кода. После того как вы узнали, что работает, вы можете рефакторить код, чтобы он стал более поддерживаемым.
Инструкции верхнего уровня упрощают программы, основанные на консольных приложениях. К этим приложениям относятся функции Azure, действия GitHub и другие небольшие служебные программы. Дополнительные сведения см. в инструкций верхнего уровня (руководство по программированию на C#).