Заметка
Доступ к этой странице требует авторизации. Вы можете попробовать войти в систему или изменить каталог.
Доступ к этой странице требует авторизации. Вы можете попробовать сменить директорию.
Приложения на основе файлов — это программы, содержащиеся в одном *.cs файле, который создается и выполняется без соответствующего файла проекта .*.csproj Приложения на основе файлов идеально подходят для обучения C#, так как они имеют меньшую сложность: вся программа хранится в одном файле. Приложения на основе файлов также полезны для создания служебных программ командной строки. На платформах Unix можно запускать приложения на основе файлов с помощью #!директив (shebang).
Изучив это руководство, вы:
- Создайте файловую программу.
- Добавьте поддержку Unix Shebang (
#!). - Чтение аргументов командной строки.
- Обработка стандартных входных данных.
- Запись выходных данных искусства ASCII.
- Обработка аргументов командной строки.
- Используйте проанализированные результаты командной строки.
- Протестируйте окончательное приложение.
Вы создаете файловую программу, которая записывает текст как искусство ASCII. Приложение содержится в одном файле, использует пакеты NuGet, реализующие некоторые основные функции.
Предпосылки
- Пакет SDK для .NET 10. Скачайте его с сайта загрузки .NET.
- Visual Studio Code. Скачайте его на домашней странице Visual Studio Code.
- (Необязательно) Расширение C# DevKit для Visual Studio Code. Скачайте его из Visual Studio Code Marketplace.
Создание файловой программы
Откройте Visual Studio Code и создайте новый файл с именем
AsciiArt.cs. Введите следующий текст:Console.WriteLine("Hello, world!");Сохраните файл. Затем откройте интегрированный терминал в Visual Studio Code и введите следующее:
dotnet run AsciiArt.cs
При первом запуске этой программы dotnet узел создает исполняемый файл из исходного файла, сохраняет артефакты сборки во временной папке, а затем запускает созданный исполняемый файл. Этот интерфейс можно проверить, введя dotnet run AsciiArt.cs еще раз. На dotnet этот раз узел определяет, что исполняемый файл является текущим, и запускает исполняемый файл, не создавая его снова. Выходные данные сборки не отображаются.
В предыдущих шагах показано, что приложения на основе файлов не являются файлами скриптов. Они представляют собой исходные файлы C#, созданные с помощью созданного файла проекта во временной папке. Одна из строк выходных данных, отображаемых при создании программы, должна выглядеть примерно так (в Windows):
AsciiArt succeeded (7.3s) → AppData\Local\Temp\dotnet\runfile\AsciiArt-85c58ae0cd68371711f06f297fa0d7891d0de82afde04d8c64d5f910ddc04ddc\bin\debug\AsciiArt.dll
На платформах UNIX папка выходных данных похожа на следующую:
AsciiArt succeeded (7.3s) → Library/Application Support/dotnet/runfile/AsciiArt-85c58ae0cd68371711f06f297fa0d7891d0de82afde04d8c64d5f910ddc04ddc/bin/debug/AsciiArt.dll
Эти выходные данные сообщают о том, где размещаются временные файлы и выходные данные сборки. В этом руководстве в любое время, когда вы редактируете исходный файл, dotnet узел обновляет исполняемый файл перед его запуском.
Приложения на основе файлов — это обычные программы C#. Единственное ограничение заключается в том, что они должны быть записаны в один исходный файл. Операторы верхнего уровня или классический Main метод можно использовать как точку входа. Можно объявить любые типы: классы, интерфейсы и структуры. Алгоритмы можно структурировать в файловой программе так же, как и в любой программе C#. Можно даже объявить несколько пространств имен для упорядочивания кода. Если программа на основе файлов растет слишком большой для одного файла, ее можно преобразовать в программу на основе проекта и разделить источник на несколько файлов. Приложения на основе файлов — это отличный инструмент прототипа. Вы можете начать экспериментировать с минимальными затратами, чтобы доказать концепции и алгоритмы сборки.
Поддержка Unix Shebang (#!)
Замечание
#! Поддержка директив применяется только на платформах UNIX. Для Windows нет аналогичной директивы для непосредственного выполнения программы C#. В Windows необходимо использовать dotnet run в командной строке.
В unix можно напрямую запускать приложения на основе файлов, введя имя исходного файла в командной строке вместо dotnet run. Необходимо внести два изменения:
Задайте разрешения на выполнение исходного файла:
chmod +x AsciiArt.csДобавьте директиву shebang (
#!) в качестве первой строкиAsciiArt.csфайла:#!/usr/local/share/dotnet/dotnet run
Расположение dotnet может отличаться в разных установках unix. Используйте команду which dotnet, чтобы найти хост в вашей dotnet среде.
Кроме того, можно использовать #!/usr/bin/env dotnet для автоматического разрешения пути dotnet из переменной среды PATH:
#!/usr/bin/env dotnet
После внесения этих двух изменений вы можете запустить программу из командной строки напрямую:
./AsciiArt.cs
Если вы предпочитаете, вы можете удалить расширение, чтобы вместо этого ввести ./AsciiArt его. Вы можете добавить его в исходный #! файл, даже если используется Windows. Командная строка Windows не поддерживается #!, но компилятор C# разрешает директиву в приложениях на основе файлов на всех платформах.
Чтение аргументов командной строки
Теперь напишите все аргументы в командной строке в выходные данные.
Замените текущее содержимое
AsciiArt.csследующим кодом:if (args.Length > 0) { string message = string.Join(' ', args); Console.WriteLine(message); }Чтобы запустить эту версию, введите следующую команду:
dotnet run AsciiArt.cs -- This is the command line.Параметр
--указывает, что все следующие аргументы команд должны передаваться в программу AsciiArt. АргументыThis is the command line.передаются в виде массива строк, где каждая строка — одно слово:This,is,theиcommandline..
Эта версия демонстрирует следующие новые понятия:
- Аргументы командной строки передаются программе с помощью предопределенной переменной
args. Переменнаяargsпредставляет собой массив строк:string[]Если длинаargsравна 0, это означает, что аргументы не были предоставлены. В противном случае каждое слово в списке аргументов хранится в соответствующей записи в массиве. - Метод
string.Joinобъединяет несколько строк в одну строку с указанным разделителем. В этом случае разделитель является одним пробелом. - Console.WriteLine записывает строку в стандартную выходную консоль, за которой следует новая строка.
Обработка стандартных входных данных
Это правильно обрабатывает аргументы командной строки. Теперь добавьте код для обработки входных данных из стандартных входных данных (stdin) вместо аргументов командной строки.
Добавьте следующее
elseпредложение в инструкциюif, добавленную в предыдущем коде:else { while (Console.ReadLine() is string line && line.Length > 0) { Console.WriteLine(line); } }Предыдущий код считывает входные данные консоли до тех пор, пока не будет прочитана пустая строка или чтение
null. (Метод возвращает, Console.ReadLinenullесли входной поток закрыт, введя ctrl+C.)Проверьте стандартные входные данные, создав текстовый файл в той же папке. Назовите файл
input.txtи добавьте следующие строки:Hello from ... dotnet! You can create file-based apps in .NET 10 and C# 14 Have fun writing useful utilitiesОставьте строки короткими, чтобы они правильно форматируются при добавлении функции для использования искусства ASCII.
Снова запустите программу.
С bash:
cat input.txt | dotnet run AsciiArt.csИли с помощью PowerShell:
Get-Content input.txt | dotnet run AsciiArt.cs
Теперь программа может принимать аргументы командной строки или стандартные входные данные.
Запись выходных данных ASCII Art
Затем добавьте пакет, поддерживающий искусство ASCII, Colorful.Console. Чтобы добавить пакет в файловую программу, используйте директиву #:package .
Добавьте следующую директиву после директивы
#!в файле AsciiArt.cs:#:package Colorful.Console@1.2.15Это важно
Последняя версия
1.2.15пакета была последнейColorful.Consoleверсией пакета, когда это руководство было последнее обновление. Проверьте страницу NuGet пакета для последней версии, чтобы убедиться, что вы используете версию пакета с последними исправлениями безопасности.Измените строки, вызываемые
Console.WriteLineметодомColorful.Console.WriteAscii, вместо этого:async Task WriteAsciiArt(AsciiMessageOptions options) { foreach (string message in options.Messages) { Colorful.Console.WriteAscii(message); await Task.Delay(options.Delay); } }Запустите программу, и вы увидите выходные данные искусства ASCII вместо эхо-текста.
Параметры команды обработки
Затем добавим синтаксический анализ командной строки. Текущая версия записывает каждое слово в виде другой строки выходных данных. Добавленные аргументы командной строки поддерживают две функции:
Процитировать несколько слов, которые должны быть написаны на одной строке:
AsciiArt.cs "This is line one" "This is another line" "This is the last line"Добавьте параметр для приостановки между каждой
--delayстрокой:AsciiArt.cs --delay 1000
Пользователи должны совместно использовать оба аргумента.
Большинство приложений командной строки должны анализировать аргументы командной строки для эффективной обработки параметров, команд и ввода пользователем. Библиотека System.CommandLine предоставляет комплексные возможности для обработки команд, вложенных команд, параметров и аргументов, что позволяет сосредоточиться на том, что делает приложение, а не механика синтаксического анализа входных данных командной строки.
Библиотека System.CommandLine предлагает несколько ключевых преимуществ:
- Автоматическое создание и проверка текста справки.
- Поддержка соглашений о командной строке POSIX и Windows.
- Встроенные возможности завершения вкладок.
- Согласованное поведение синтаксического анализа между приложениями.
System.CommandLineДобавьте пакет. Добавьте эту директиву после существующей директивы пакета:#:package System.CommandLine@2.0.0Это важно
Версия была последней версией
2.0.0, когда это руководство было последнее обновление. Если доступна более новая версия, используйте последнюю версию, чтобы обеспечить наличие последних пакетов безопасности. Проверьте страницу NuGet пакета для последней версии, чтобы убедиться, что вы используете версию пакета с последними исправлениями безопасности.Добавьте необходимые инструкции using в верхней части файла (после
#!и#:packageдиректив):using System.CommandLine; using System.CommandLine.Parsing;Определите параметр задержки и аргумент сообщений. Добавьте следующий код для создания
CommandLine.OptionиCommandLine.Argumentобъектов для представления параметра командной строки и аргумента:Option<int> delayOption = new("--delay") { Description = "Delay between lines, specified as milliseconds.", DefaultValueFactory = parseResult => 100 }; Argument<string[]> messagesArgument = new("Messages") { Description = "Text to render." };В приложениях командной строки параметры обычно начинаются с
--(двойной дефис) и могут принимать аргументы. Параметр--delayпринимает целый аргумент, указывающий задержку в миллисекундах. ОпределяетmessagesArgument, как все остальные маркеры после анализа параметров анализируются как текст. Каждый маркер становится отдельной строкой в массиве, но текст может быть кавычек, чтобы включить несколько слов в один маркер. Например,"This is one message"становится одним маркером, аThis is four tokensстановится четырьмя отдельными маркерами.Предыдущий код определяет тип аргумента для
--delayпараметра и что аргументы являются массивом значенийstring. Это приложение имеет только одну команду, поэтому вы используете корневую команду.Создайте корневую команду и настройте ее с помощью параметра и аргумента. Добавьте аргумент и параметр в корневую команду:
RootCommand rootCommand = new("Ascii Art file-based program sample"); rootCommand.Options.Add(delayOption); rootCommand.Arguments.Add(messagesArgument);Добавьте код для синтаксического анализа аргументов командной строки и обработки ошибок. Этот код проверяет аргументы командной строки и сохраняет проанализированные аргументы в объекте System.CommandLine.ParseResult :
ParseResult result = rootCommand.Parse(args); foreach (ParseError parseError in result.Errors) { Console.Error.WriteLine(parseError.Message); } if (result.Errors.Count > 0) { return 1; }
Предыдущий код проверяет все аргументы командной строки. Если проверка завершается ошибкой, ошибки записываются в консоль и приложение завершается.
Использование проанализированных результатов командной строки
Теперь завершите работу приложения для использования параметров синтаксического анализа и записи выходных данных. Сначала определите запись для хранения параметров синтаксического анализа. Приложения на основе файлов могут включать объявления типов, такие как записи и классы. Они должны быть после всех инструкций верхнего уровня и локальных функций.
recordДобавьте объявление для хранения сообщений и значения параметра задержки:public record AsciiMessageOptions(string[] Messages, int Delay);Добавьте следующую локальную функцию перед объявлением записи. Этот метод обрабатывает аргументы командной строки и стандартные входные данные и возвращает новый экземпляр записи:
async Task<AsciiMessageOptions> ProcessParseResults(ParseResult result) { int delay = result.GetValue(delayOption); List<string> messages = [.. result.GetValue(messagesArgument) ?? Array.Empty<string>()]; if (messages.Count == 0) { while (Console.ReadLine() is string line && line.Length > 0) { Colorful.Console.WriteAscii(line); await Task.Delay(delay); } } return new([.. messages], delay); }Создайте локальную функцию для записи искусства ASCII с указанной задержкой. Эта функция записывает каждое сообщение в записи с указанной задержкой между каждым сообщением:
async Task WriteAsciiArt(AsciiMessageOptions options) { foreach (string message in options.Messages) { Colorful.Console.WriteAscii(message); await Task.Delay(options.Delay); } }Замените
ifпредложение, написанного ранее, следующим кодом, который обрабатывает аргументы командной строки и записывает выходные данные:var parsedArgs = await ProcessParseResults(result); await WriteAsciiArt(parsedArgs); return 0;
Вы создали record тип, который предоставляет структуру для параметров и аргументов командной строки синтаксического анализа. Новые локальные функции создают экземпляр записи и используют запись для записи выходных данных искусства ASCII.
Тестирование окончательного приложения
Протестируйте приложение, выполнив несколько различных команд. Если у вас возникли проблемы, вот готовый пример для сравнения с тем, что вы создали:
#!/usr/local/share/dotnet/dotnet run
#:package Colorful.Console@1.2.15
#:package System.CommandLine@2.0.0
using System.CommandLine;
using System.CommandLine.Parsing;
Option<int> delayOption = new("--delay")
{
Description = "Delay between lines, specified as milliseconds.",
DefaultValueFactory = parseResult => 100
};
Argument<string[]> messagesArgument = new("Messages")
{
Description = "Text to render."
};
RootCommand rootCommand = new("Ascii Art file-based program sample");
rootCommand.Options.Add(delayOption);
rootCommand.Arguments.Add(messagesArgument);
ParseResult result = rootCommand.Parse(args);
foreach (ParseError parseError in result.Errors)
{
Console.Error.WriteLine(parseError.Message);
}
if (result.Errors.Count > 0)
{
return 1;
}
var parsedArgs = await ProcessParseResults(result);
await WriteAsciiArt(parsedArgs);
return 0;
async Task<AsciiMessageOptions> ProcessParseResults(ParseResult result)
{
int delay = result.GetValue(delayOption);
List<string> messages = [.. result.GetValue(messagesArgument) ?? Array.Empty<string>()];
if (messages.Count == 0)
{
while (Console.ReadLine() is string line && line.Length > 0)
{
// <WriteAscii>
Colorful.Console.WriteAscii(line);
// </WriteAscii>
await Task.Delay(delay);
}
}
return new([.. messages], delay);
}
async Task WriteAsciiArt(AsciiMessageOptions options)
{
foreach (string message in options.Messages)
{
Colorful.Console.WriteAscii(message);
await Task.Delay(options.Delay);
}
}
public record AsciiMessageOptions(string[] Messages, int Delay);
В этом руководстве вы узнали, как создать файловую программу, в которой вы создаете программу в одном файле C#. Эти программы не используют файл проекта и могут использовать директиву #! в системах UNIX. Учащиеся могут создавать эти программы после работы с нашими онлайн-учебниками и перед созданием более крупных приложений на основе проектов. Приложения на основе файлов также являются отличной платформой для служебных программ командной строки.