Примечание.
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
Приложения на основе файлов — это программы, содержащиеся в одном *.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 AsciiArt.cs
При первом запуске этой программы dotnet хост создает исполняемый файл из вашего исходного файла, сохраняет артефакты сборки во временной папке, а затем запускает созданный исполняемый файл. Этот опыт можно проверить, введя dotnet AsciiArt.cs еще раз. На этот раз dotnet хост определяет, что исполняемый файл является актуальным и запускает его без повторной сборки. Выходные данные сборки не отображаются.
В предыдущих шагах показано, что приложения на основе файлов не являются файлами скриптов. Это исходные файлы C#, которые dotnet хост создает с помощью сгенерированного файла проекта во временной папке. Одна из строк выходных данных, отображаемых при сборке программы, должна выглядеть примерно так (в 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 в командной строке.
В Unix запустите приложения на основе файлов непосредственно, введя только имя исходного файла. Вместо использования dotnet AsciiArt.csвведите имя исходного файла в командной строке. Необходимо внести два изменения:
Задайте разрешения на выполнение исходного файла:
chmod +x AsciiArt.csДобавьте директиву shebang (
#!) в качестве первой строкиAsciiArt.csфайла:#!/usr/local/share/dotnet/dotnet
Расположение 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 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.ReadLine возвращаетnull, если входной поток закрыт при нажатии 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 AsciiArt.csИли с помощью PowerShell:
Get-Content input.txt | dotnet AsciiArt.cs
Теперь программа может принимать аргументы командной строки или стандартные входные данные.
Написать ASCII-арт
Затем добавьте пакет, поддерживающий искусство ASCII, Colorful.Console. Чтобы добавить пакет в файловое приложение, используйте директиву #:package .
Добавьте следующую директиву после директивы
#!вAsciiArt.csфайле:#:package Colorful.Console@1.2.15Это важно
Версия
1.2.15была последней версией пакетаColorful.Console, когда это руководство было в последний раз обновлено. Проверьте страницу NuGet пакета для последней версии, чтобы убедиться, что вы используете версию пакета с последними исправлениями безопасности.Измените строки таким образом, чтобы вместо вызова
Console.WriteLineиспользовался методColorful.Console.WriteAscii.Colorful.Console.WriteAscii(line);Запустите программу. Вы видите вывод 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 app 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/bin/env dotnet
#: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 app 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. Учащиеся могут создавать эти программы после работы с нашими онлайн-учебниками и перед созданием более крупных приложений на основе проектов. Приложения на основе файлов также являются отличной платформой для служебных программ командной строки.