Not
Åtkomst till denna sida kräver auktorisation. Du kan prova att logga in eller byta katalog.
Åtkomst till denna sida kräver auktorisation. Du kan prova att byta katalog.
Filbaserade appar är program som finns i en enda *.cs fil som du skapar och kör utan motsvarande projektfil (*.csproj). Filbaserade appar är idealiska för att lära sig C# eftersom de har mindre komplexitet: Hela programmet lagras i en enda fil. Filbaserade appar är också användbara för att skapa kommandoradsverktyg. På Unix-plattformar kan du köra filbaserade appar med hjälp #! av (shebang)- direktiv.
I den här handledningen kommer du att:
- Skapa ett filbaserat program.
- Lägg till Stöd för Unix shebang (
#!). - Läsa kommandoradsargument.
- Hantera standardindata.
- Skriv ASCII-konstutdata.
- Bearbeta kommandoradsargument.
- Använd parsade kommandoradsresultat.
- Testa det slutliga programmet.
Du skapar ett filbaserat program som skriver text som ASCII-konst. Appen finns i en enda fil, använder NuGet-paket och implementerar kärnfunktioner.
Förutsättningar
- The .NET 10 SDK. Ladda ned den från nedladdningswebbplatsen för .NET.
- Visual Studio Code. Ladda ned den från Visual Studio Code-startsidan.
- (Valfritt) C# DevKit-tillägget för Visual Studio Code. Ladda ned den från Visual Studio Code Marketplace.
Skapa ett filbaserat program
Öppna Visual Studio Code och skapa en ny fil med namnet
AsciiArt.cs. Ange följande text:Console.WriteLine("Hello, world!");Spara filen. Öppna sedan den integrerade terminalen i Visual Studio Code och skriv:
dotnet run AsciiArt.cs
Första gången du kör det här programmet dotnet skapar värden den körbara filen från din källfil, lagrar byggrelaterade filer i en tillfällig mapp och därefter körs den skapade körbara filen. Du kan verifiera den här upplevelsen genom att dotnet run AsciiArt.cs skriva igen. Den här gången dotnet avgör värden att den körbara filen är aktuell och kör den körbara filen utan att skapa den igen. Du ser inga build-utdata.
Föregående steg visar att filbaserade appar inte är skriptfiler. Det är C#-källfiler som hosten dotnet skapar med hjälp av en genererad projektfil i en tillfällig mapp. En av de utdatarader som visas när du skapar programmet bör se ut ungefär så här (i Windows):
AsciiArt succeeded (7.3s) → AppData\Local\Temp\dotnet\runfile\AsciiArt-85c58ae0cd68371711f06f297fa0d7891d0de82afde04d8c64d5f910ddc04ddc\bin\debug\AsciiArt.dll
På Unix-plattformar liknar utdatamappen följande:
AsciiArt succeeded (7.3s) → Library/Application Support/dotnet/runfile/AsciiArt-85c58ae0cd68371711f06f297fa0d7891d0de82afde04d8c64d5f910ddc04ddc/bin/debug/AsciiArt.dll
Utdata anger var de temporära filerna och byggutdata placeras. I den här självstudien, när du redigerar källfilen, dotnet uppdaterar värden den körbara filen innan den körs.
Filbaserade appar är vanliga C#-program. Den enda begränsningen är att du måste skriva dem i en källfil. Du kan använda toppnivåinstruktioner eller en klassisk Main metod som startpunkt. Du kan deklarera alla typer: klasser, gränssnitt och structs. Du kan strukturera algoritmerna i ett filbaserat program på samma sätt som i alla C#-program. Du kan till och med deklarera flera namnområden för att organisera koden. Om du upptäcker att ett filbaserat program blir för stort för en enskild fil kan du konvertera det till ett projektbaserat program och dela upp källan i flera filer. Filbaserade appar är ett bra prototypverktyg. Du kan börja experimentera med minimala omkostnader för att bevisa begrepp och bygga algoritmer.
Stöd för Unix shebang (#!)
Anmärkning
Stöd för #! direktiv gäller endast på Unix-plattformar. Det finns inget liknande direktiv för Windows att köra ett C#-program direkt. I Windows måste du använda dotnet run på kommandoraden.
På Unix kan du köra filbaserade appar direkt. I stället för att använda dotnet runskriver du källfilnamnet på kommandoraden. Du måste göra två ändringar:
Ange körningsbehörigheter för källfilen:
chmod +x AsciiArt.csLägg till ett shebang-direktiv (
#!) som den första raden iAsciiArt.csfilen:#!/usr/local/share/dotnet/dotnet run
Platsen för dotnet kan vara olika för olika Unix-installationer. Använd kommandot which dotnet för att hitta dotnet host i din miljö.
Alternativt kan du använda #!/usr/bin/env dotnet för att automatiskt bestämma dotnet-sökvägen ur PATH-miljövariabeln.
#!/usr/bin/env dotnet
När du har gjort dessa två ändringar kan du köra programmet direkt från kommandoraden:
./AsciiArt.cs
Om du vill kan du ta bort tillägget så att du kan skriva ./AsciiArt i stället. Du kan lägga till i #! källfilen även om du använder Windows. Windows-kommandoraden stöder #!inte , men C#-kompilatorn tillåter det direktivet i filbaserade appar på alla plattformar.
Läsa kommandoradsargument
Skriv nu alla argument på kommandoraden till utdata.
Ersätt det aktuella innehållet i
AsciiArt.csmed följande kod:if (args.Length > 0) { string message = string.Join(' ', args); Console.WriteLine(message); }Du kan köra den här versionen genom att skriva följande kommando:
dotnet run AsciiArt.cs -- This is the command line.Alternativet
--anger att alla följande kommandoargument ska skickas till AsciiArt-programmet. ArgumentenThis is the command line.skickas som en matris med strängar, där varje sträng är ett ord:This,is,the,commandochline..
Den här versionen visar dessa nya begrepp:
- Den fördefinierade variabeln
argsskickar kommandoradsargumenten till programmet. Variabelnargsär en matris med strängar:string[]. Om längdenargspå är 0 angavs inga argument. Annars lagras varje ord i argumentlistan i motsvarande post i matrisen. - Metoden
string.Joinkopplar flera strängar till en enda sträng med den angivna avgränsaren. I det här fallet är avgränsaren ett enda blanksteg. - Console.WriteLine skriver strängen till standardutdatakonsolen följt av en ny rad.
Hantera standardindata
Föregående kod hanterar kommandoradsargument korrekt. Lägg nu till koden för att hantera läsindata från standardindata (stdin) i stället för kommandoradsargument.
Lägg till följande
elsesats i -instruktionenifsom du lade till i föregående kod:else { while (Console.ReadLine() is string line && line.Length > 0) { Console.WriteLine(line); } }Föregående kod läser konsolens indata tills antingen en tom rad eller en
nulllästs. (Metoden Console.ReadLine returnerarnullom indataströmmen stängs genom att skriva ctrl+C.)Testa att läsa standardindata genom att skapa en ny textfil i samma mapp. Namnge filen
input.txtoch lägg till följande rader:Hello from ... dotnet! You can create file-based apps in .NET 10 and C# 14 Have fun writing useful utilitiesHåll linjerna korta så att de formateras korrekt när du lägger till funktionen för att använda ASCII-konst.
Kör programmet igen.
Genom att använda bash:
cat input.txt | dotnet run AsciiArt.csEller genom att använda PowerShell:
Get-Content input.txt | dotnet run AsciiArt.cs
Nu kan programmet acceptera antingen kommandoradsargument eller standardindata.
Skriv ut ASCII-konst
Lägg sedan till ett paket som stöder ASCII-konst, Colorful.Console. Om du vill lägga till ett paket i ett filbaserat program använder du #:package direktivet.
Lägg till följande direktiv efter
#!direktivet i filenAsciiArt.cs:#:package Colorful.Console@1.2.15Viktigt!
Versionen
1.2.15var den senaste versionen avColorful.Consolepaketet när den här självstudien senast uppdaterades. Kontrollera paketets NuGet-sida för den senaste versionen för att se till att du använder en paketversion med de senaste säkerhetskorrigeringarna.Ändra de rader som anropar
Console.WriteLineför att användaColorful.Console.WriteAsciimetoden i stället:Colorful.Console.WriteAscii(line);Kör programmet. Du ser ASCII-konstutdata i stället för ekade text.
Processkommandoalternativ
Lägg sedan till kommandoradsparsning. Den aktuella versionen skriver varje ord som en annan rad med utdata. De kommandoradsargument som du lägger till stöder två funktioner:
Citera flera ord som ska skrivas på en rad:
AsciiArt.cs "This is line one" "This is another line" "This is the last line"Lägg till ett
--delayalternativ för att pausa mellan varje rad:AsciiArt.cs --delay 1000
Användarna kan använda båda argumenten tillsammans.
De flesta kommandoradsprogram behöver parsa kommandoradsargument för att hantera alternativ, kommandon och användarindata effektivt.
BiblioteketSystem.CommandLine innehåller omfattande funktioner för att hantera kommandon, underkommandon, alternativ och argument. Du kan koncentrera dig på vad programmet gör i stället för mekaniken för att parsa indata från kommandoraden.
Biblioteket System.CommandLine har flera viktiga fördelar:
- Automatisk textgenerering och validering av hjälp.
- Stöd för POSIX- och Windows-kommandoradskonventioner.
- Inbyggda funktioner för flikkomplettering.
- Konsekvent parsningsbeteende mellan program.
System.CommandLineLägg till paketet. Lägg till det här direktivet efter det befintliga paketdirektivet:#:package System.CommandLine@2.0.0Viktigt!
Versionen
2.0.0var den senaste versionen när den här självstudien senast uppdaterades. Om det finns en nyare version tillgänglig använder du den senaste versionen för att se till att du har de senaste säkerhetspaketen. Kontrollera paketets NuGet-sida för den senaste versionen för att se till att du använder en paketversion med de senaste säkerhetskorrigeringarna.Lägg till nödvändiga användningsinstruktioner överst i filen (efter direktiven
#!och#:package):using System.CommandLine; using System.CommandLine.Parsing;Definiera argumentet fördröjning och meddelanden. Lägg till följande kod för att skapa objekten
CommandLine.OptionochCommandLine.Argumentför att representera kommandoradsalternativet och argumentet:Option<int> delayOption = new("--delay") { Description = "Delay between lines, specified as milliseconds.", DefaultValueFactory = parseResult => 100 }; Argument<string[]> messagesArgument = new("Messages") { Description = "Text to render." };I kommandoradsprogram börjar alternativen vanligtvis med
--(dubbel bindestreck) och kan acceptera argument. Alternativet--delayaccepterar ett heltalsargument som anger fördröjningen i millisekunder. DefinierarmessagesArgumenthur eventuella återstående token efter alternativ parsas som text. Varje token blir en separat sträng i matrisen, men text kan citeras för att inkludera flera ord i en token. Till exempel"This is one message"blir en enda token, medanThis is four tokensblir fyra separata token.Föregående kod definierar argumenttypen för
--delayalternativet och att argumenten är en matris medstringvärden. Det här programmet har bara ett kommando, så du använder rotkommandot.Skapa ett rotkommando och konfigurera det med alternativet och argumentet. Lägg till argumentet och alternativet i rotkommandot:
RootCommand rootCommand = new("Ascii Art file-based program sample"); rootCommand.Options.Add(delayOption); rootCommand.Arguments.Add(messagesArgument);Lägg till koden för att parsa kommandoradsargumenten och hantera eventuella fel. Den här koden validerar kommandoradsargumenten och lagrar parsade argument i System.CommandLine.ParseResult objektet:
ParseResult result = rootCommand.Parse(args); foreach (ParseError parseError in result.Errors) { Console.Error.WriteLine(parseError.Message); } if (result.Errors.Count > 0) { return 1; }
Föregående kod verifierar alla kommandoradsargument. Om verifieringen misslyckas skriver appen fel till konsolen och avslutas.
Använda parsade kommandoradsresultat
Slutför nu appen för att använda de parsade alternativen och skriva utdata. Definiera först en post som ska innehålla de parsade alternativen. Filbaserade appar kan innehålla typdeklarationer, till exempel poster och klasser. De måste vara efter alla toppnivåinstruktioner och lokala funktioner.
Lägg till en
recorddeklaration för att lagra meddelandena och alternativet för fördröjning:public record AsciiMessageOptions(string[] Messages, int Delay);Lägg till följande lokala funktion före postdeklarationen. Den här metoden hanterar både kommandoradsargument och standardindata och returnerar en ny postinstans:
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); }Skapa en lokal funktion för att skriva ASCII-konsten med den angivna fördröjningen. Den här funktionen skriver varje meddelande i posten med den angivna fördröjningen mellan varje meddelande:
async Task WriteAsciiArt(AsciiMessageOptions options) { foreach (string message in options.Messages) { Colorful.Console.WriteAscii(message); await Task.Delay(options.Delay); } }ifErsätt satsen som du skrev tidigare med följande kod som bearbetar kommandoradsargumenten och skriver utdata:var parsedArgs = await ProcessParseResults(result); await WriteAsciiArt(parsedArgs); return 0;
Du har skapat en record typ som ger struktur åt de parsade kommandoradsalternativen och argumenten. Nya lokala funktioner skapar en instans av posten och använder posten för att skriva ASCII-konstutdata.
Testa det slutliga programmet
Testa programmet genom att köra flera olika kommandon. Om du har problem kan du jämföra det här exemplet med det du har skapat:
#!/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);
I den här självstudien har du lärt dig att skapa ett filbaserat program, där du skapar programmet i en enda C#-fil. De här programmen använder inte en projektfil och kan använda #! direktivet om Unix-system. Elever kan skapa dessa program efter att ha provat våra online-självstudier och innan de skapar större projektbaserade appar. Filbaserade appar är också en bra plattform för kommandoradsverktyg.