Esercitazione: Estendere l'app console C# ed eseguire il debug in Visual Studio (parte 2 di 2)
In questo articolo
Nella parte 2 di questa serie di esercitazioni si approfondirà le funzionalità di compilazione e debug di Visual Studio necessarie per lo sviluppo giornaliero. Queste funzionalità includono la gestione di più progetti, debug e riferimento a pacchetti di terze parti. Esegui l'app console C# che hai creato nella Parte 1 di di questa esercitazioneed esplora alcune funzionalità dell'ambiente di sviluppo integrato (IDE) di Visual Studio. Questa esercitazione è la parte 2 di una serie di esercitazioni in due parti.
In questa esercitazione vengono completate le attività seguenti:
- Aggiungere un secondo progetto.
- Librerie di riferimento e aggiungere pacchetti.
- Eseguire il debug del codice.
- Ispeziona il codice completato.
Per eseguire questo articolo, è possibile usare una di queste app calcolatrice:
- L'app console calcolatrice della parte 1 di questo tutorial.
- L'app calcolatrice C# nel repo vs-tutorial-samples . Per iniziare, aprire l'app dal repository.
Il codice reale prevede progetti che interagiscono tra loro in una soluzione. È possibile aggiungere un progetto di libreria di classi all'app calcolatrice che fornisce alcune funzioni di calcolatrice.
In Visual Studio si usa il comando di menu File>Aggiungi>Nuovo progetto per aggiungere un nuovo progetto. È anche possibile fare clic con il pulsante destro del mouse sulla soluzione in Esplora soluzioni per aggiungere un progetto dal menu di scelta rapida.
In Esplora soluzioni fare clic con il pulsante destro del mouse sul nodo della soluzione e scegliere Aggiungi>Nuovo progetto.
Nella finestra Aggiungi un nuovo progetto digitare libreria di classi nella casella di ricerca. Scegliere il modello di progetto della libreria di classi C# e quindi selezionare Avanti.
Nella schermata Configura il nuovo progetto digitare il nome del progetto CalculatorLibrarye quindi selezionare Avanti.
Scegliere .NET 3.1 quando richiesto. Visual Studio crea il nuovo progetto e lo aggiunge alla soluzione.
Rinominare il file Class1.cs in CalculatorLibrary.cs. Per rinominare il file, è possibile fare clic con il pulsante destro del mouse sul nome in Esplora soluzioni e scegliere Rinomina, selezionare il nome e premere F2oppure selezionare di nuovo il nome e selezionare di nuovo per digitare.
Un messaggio potrebbe chiedere se si desidera rinominare i riferimenti a
Class1
nel file. Non importa come rispondere, perché il codice verrà sostituito in un passaggio futuro.Aggiungere ora un riferimento al progetto, in modo che il primo progetto possa usare le API esposte dalla nuova libreria di classi. Fare clic con il pulsante destro del mouse sul nodo Dipendenze nel progetto Calcolatrice e scegliere Aggiungi riferimento al progetto.
Viene visualizzata la finestra di dialogo Gestione Riferimenti. In questa finestra di dialogo è possibile aggiungere riferimenti ad altri progetti, assembly e DLL COM necessari per i progetti.
Nella finestra di dialogo Gestione riferimenti, selezionare la casella di controllo per il progetto CalculatorLibrary e quindi selezionare OK.
Il riferimento al progetto viene visualizzato in un nodo Progetti in Esplora soluzioni .
In Program.csselezionare la classe
Calculator
e tutto il codice e premere CTRL+X per tagliarla. Quindi, in CalculatorLibrary.cs, incollare il codice nello spazio dei nomiCalculatorLibrary
.Aggiungere anche
public
prima della classe Calculator per renderla visibile fuori dalla libreria.CalculatorLibrary.cs dovrebbe ora essere simile al codice seguente:
// CalculatorLibrary.cs using System; namespace CalculatorLibrary { public class Calculator { public static double DoOperation(double num1, double num2, string op) { double result = double.NaN; // Default value is "not-a-number" if an operation, such as division, could result in an error. // Use a switch statement to do the math. switch (op) { case "a": result = num1 + num2; break; case "s": result = num1 - num2; break; case "m": result = num1 * num2; break; case "d": // Ask the user to enter a non-zero divisor. if (num2 != 0) { result = num1 / num2; } break; // Return text for an incorrect option entry. default: break; } return result; } } }
Program.cs ha anche un riferimento, ma un errore indica che la chiamata
Calculator.DoOperation
non viene risolta. L'errore è dovuto al fatto cheCalculatorLibrary
si trova in uno spazio dei nomi diverso. Per un riferimento completo, è possibile aggiungere lo spazio dei nomiCalculatorLibrary
alla chiamataCalculator.DoOperation
nel file Program.cs:// Program.cs result = CalculatorLibrary.Calculator.DoOperation(cleanNum1, cleanNum2, op);
In alternativa, è possibile provare ad aggiungere una direttiva
using
all'inizio del file Program.cs:// Program.cs using CalculatorLibrary;
L'aggiunta della direttiva
using
dovrebbe consentire di rimuovere lo spazio dei nomiCalculatorLibrary
dal sito di chiamata, ma ora esiste un'ambiguità. ÈCalculator
la classe inCalculatorLibrary
o èCalculator
il namespace?Per risolvere l'ambiguità, rinominare lo spazio dei nomi da
Calculator
inCalculatorProgram
in Program.cs.// Program.cs namespace CalculatorProgram
In Esplora soluzioni fare clic con il pulsante destro del mouse sul nodo della soluzione e scegliere Aggiungi>Nuovo progetto.
Nella finestra Aggiungi un nuovo progetto, digitare libreria di classi nella casella di ricerca. Scegliere il modello di progetto della libreria di classi C#, e quindi selezionare Avanti.
Nella schermata Configura il nuovo progetto digitare il nome del progetto CalculatorLibrarye quindi selezionare Avanti.
Nella schermata Informazioni aggiuntive è selezionato .NET 8.0. Selezionare Crea.
Visual Studio crea il nuovo progetto e lo aggiunge alla soluzione.
Rinominare il file Class1.cs in CalculatorLibrary.cs. Per rinominare il file, è possibile fare clic con il pulsante destro del mouse sul nome in Esplora soluzioni e scegliere Rinomina, selezionare il nome e premere F2oppure selezionare di nuovo il nome e selezionare di nuovo per digitare.
Un messaggio potrebbe chiedere se si desidera rinominare tutti i riferimenti a
Class1
nel file. Non importa come rispondere, perché il codice verrà sostituito in un passaggio futuro.Aggiungere ora un riferimento al progetto, in modo che il primo progetto possa usare le API esposte dalla nuova libreria di classi. Fare clic con il pulsante destro del mouse sul nodo Dipendenze nel progetto Calcolatrice e scegliere Aggiungi riferimento al progetto.
Appare la finestra di dialogo Gestore Riferimenti. In questa finestra di dialogo è possibile aggiungere riferimenti ad altri progetti, assembly e DLL COM necessari per i progetti.
Nella finestra di dialogo Gestione riferimenti, selezionare la casella di controllo per il progetto CalculatorLibrary e quindi selezionare OK.
Il riferimento al progetto compare sotto un nodo Progetti in Esplora Soluzioni .
In Program.csselezionare la classe
Calculator
e tutto il codice e premere CTRL+X per tagliarla. Quindi, incollare il codice nello spazio dei nomiCalculatorLibrary
in CalculatorLibrary.cs.Aggiungere anche
public
prima della definizione della classe Calculator per esporla all'esterno della libreria.CalculatorLibrary.cs dovrebbe ora essere simile al codice seguente:
// CalculatorLibrary.cs namespace CalculatorLibrary { public class Calculator { public static double DoOperation(double num1, double num2, string op) { double result = double.NaN; // Default value is "not-a-number" if an operation, such as division, could result in an error. // Use a switch statement to do the math. switch (op) { case "a": result = num1 + num2; break; case "s": result = num1 - num2; break; case "m": result = num1 * num2; break; case "d": // Ask the user to enter a non-zero divisor. if (num2 != 0) { result = num1 / num2; } break; // Return text for an incorrect option entry. default: break; } return result; } } }
Program.cs ha anche un riferimento, ma un errore indica che la chiamata
Calculator.DoOperation
non viene risolta. L'errore è dovuto al fatto cheCalculatorLibrary
si trova in uno spazio dei nomi diverso. Per un riferimento completamente qualificato, è possibile aggiungere lo spazio dei nomiCalculatorLibrary
alla chiamataCalculator.DoOperation
in Program.cs:// Program.cs result = CalculatorLibrary.Calculator.DoOperation(cleanNum1, cleanNum2, op);
In alternativa, è possibile provare ad aggiungere una direttiva
using
all'inizio del file Program.cs:// Program.cs using CalculatorLibrary;
L'aggiunta della direttiva
using
dovrebbe consentire di rimuovere lo spazio dei nomiCalculatorLibrary
dal sito di chiamata.Se il codice
Program.cs
si trova nello spazio dei nomiCalculator
, rinominare lo spazio dei nomi daCalculator
aCalculatorProgram
per rimuovere ambiguità tra nome della classe e nome dello spazio dei nomi.
È possibile usare la classe traccia .NET per aggiungere un log di tutte le operazioni e scriverla in un file di testo. La classe Trace
è utile anche per le tecniche di debug di stampa di base. La classe Trace
si trova in System.Diagnostics
e usa classi di System.IO
come StreamWriter
.
Inizia aggiungendo le direttive
using
all'inizio di CalculatorLibrary.cs:// CalculatorLibrary.cs using System.IO; using System.Diagnostics;
Questo utilizzo della classe
Trace
deve contenere un riferimento per la classe associata a un filestream. Questo requisito indica che il calcolatore funziona meglio come oggetto, quindi aggiungere un costruttore all'inizio della classeCalculator
in CalculatorLibrary.cs.Rimuovere anche la parola chiave
static
per modificare il metodoDoOperation
statico in un metodo membro.// CalculatorLibrary.cs public Calculator() { StreamWriter logFile = File.CreateText("calculator.log"); Trace.Listeners.Add(new TextWriterTraceListener(logFile)); Trace.AutoFlush = true; Trace.WriteLine("Starting Calculator Log"); Trace.WriteLine(String.Format("Started {0}", System.DateTime.Now.ToString())); } public double DoOperation(double num1, double num2, string op) {
Aggiungere l'output del log a ogni calcolo.
DoOperation
dovrebbe ora essere simile al codice seguente:// CalculatorLibrary.cs public double DoOperation(double num1, double num2, string op) { double result = double.NaN; // Default value is "not-a-number" if an operation, such as division, could result in an error. // Use a switch statement to do the math. switch (op) { case "a": result = num1 + num2; Trace.WriteLine(String.Format("{0} + {1} = {2}", num1, num2, result)); break; case "s": result = num1 - num2; Trace.WriteLine(String.Format("{0} - {1} = {2}", num1, num2, result)); break; case "m": result = num1 * num2; Trace.WriteLine(String.Format("{0} * {1} = {2}", num1, num2, result)); break; case "d": // Ask the user to enter a non-zero divisor. if (num2 != 0) { result = num1 / num2; Trace.WriteLine(String.Format("{0} / {1} = {2}", num1, num2, result)); } break; // Return text for an incorrect option entry. default: break; } return result; }
Di ritorno a Program.csuna sottolineatura ondulata rossa ora contrassegna la chiamata statica. Per correggere l'errore, creare una variabile
calculator
aggiungendo la riga di codice seguente subito prima del ciclowhile (!endApp)
:// Program.cs Calculator calculator = new Calculator();
Modificare anche il sito di chiamata
DoOperation
per fare riferimento all'oggetto denominatocalculator
in lettere minuscole. Il codice è ora una chiamata membro, anziché una chiamata a un metodo statico.// Program.cs result = calculator.DoOperation(cleanNum1, cleanNum2, op);
Eseguire di nuovo l'app. Quando hai finito, fare clic con il pulsante destro del mouse sul nodo di progetto calcolatrice e scegliere Apri cartella in Esplora file.
In Esplora File, navigare alla cartella di output in bin/Debug/net8.0 (o qualsiasi versione di .NET in uso) e aprire il file calculator.log. L'output dovrebbe essere simile al seguente:
Starting Calculator Log Started 7/9/2020 1:58:19 PM 1 + 2 = 3 3 * 3 = 9
A questo punto, CalculatorLibrary.cs dovrebbe essere simile al codice seguente:
// CalculatorLibrary.cs
using System;
using System.IO;
using System.Diagnostics;
namespace CalculatorLibrary
{
public class Calculator
{
public Calculator()
{
StreamWriter logFile = File.CreateText("calculator.log");
Trace.Listeners.Add(new TextWriterTraceListener(logFile));
Trace.AutoFlush = true;
Trace.WriteLine("Starting Calculator Log");
Trace.WriteLine(String.Format("Started {0}", System.DateTime.Now.ToString()));
}
public double DoOperation(double num1, double num2, string op)
{
double result = double.NaN; // Default value is "not-a-number" if an operation, such as division, could result in an error.
// Use a switch statement to do the math.
switch (op)
{
case "a":
result = num1 + num2;
Trace.WriteLine(String.Format("{0} + {1} = {2}", num1, num2, result));
break;
case "s":
result = num1 - num2;
Trace.WriteLine(String.Format("{0} - {1} = {2}", num1, num2, result));
break;
case "m":
result = num1 * num2;
Trace.WriteLine(String.Format("{0} * {1} = {2}", num1, num2, result));
break;
case "d":
// Ask the user to enter a non-zero divisor.
if (num2 != 0)
{
result = num1 / num2;
Trace.WriteLine(String.Format("{0} / {1} = {2}", num1, num2, result));
}
break;
// Return text for an incorrect option entry.
default:
break;
}
return result;
}
}
}
Program.cs dovrebbe essere simile al codice seguente:
// Program.cs
using System;
using CalculatorLibrary;
namespace CalculatorProgram
{
class Program
{
static void Main(string[] args)
{
bool endApp = false;
// Display title as the C# console calculator app.
Console.WriteLine("Console Calculator in C#\r");
Console.WriteLine("------------------------\n");
Calculator calculator = new Calculator();
while (!endApp)
{
// Declare variables and set to empty.
string numInput1 = "";
string numInput2 = "";
double result = 0;
// Ask the user to type the first number.
Console.Write("Type a number, and then press Enter: ");
numInput1 = Console.ReadLine();
double cleanNum1 = 0;
while (!double.TryParse(numInput1, out cleanNum1))
{
Console.Write("This is not valid input. Please enter an integer value: ");
numInput1 = Console.ReadLine();
}
// Ask the user to type the second number.
Console.Write("Type another number, and then press Enter: ");
numInput2 = Console.ReadLine();
double cleanNum2 = 0;
while (!double.TryParse(numInput2, out cleanNum2))
{
Console.Write("This is not valid input. Please enter an integer value: ");
numInput2 = Console.ReadLine();
}
// Ask the user to choose an operator.
Console.WriteLine("Choose an operator from the following list:");
Console.WriteLine("\ta - Add");
Console.WriteLine("\ts - Subtract");
Console.WriteLine("\tm - Multiply");
Console.WriteLine("\td - Divide");
Console.Write("Your option? ");
string op = Console.ReadLine();
try
{
result = calculator.DoOperation(cleanNum1, cleanNum2, op);
if (double.IsNaN(result))
{
Console.WriteLine("This operation will result in a mathematical error.\n");
}
else Console.WriteLine("Your result: {0:0.##}\n", result);
}
catch (Exception e)
{
Console.WriteLine("Oh no! An exception occurred trying to do the math.\n - Details: " + e.Message);
}
Console.WriteLine("------------------------\n");
// Wait for the user to respond before closing.
Console.Write("Press 'n' and Enter to close the app, or press any other key and Enter to continue: ");
if (Console.ReadLine() == "n") endApp = true;
Console.WriteLine("\n"); // Friendly linespacing.
}
return;
}
}
}
È possibile usare la classe traccia .NET per aggiungere un log di tutte le operazioni e scriverla in un file di testo. La classe Trace
è utile anche per le tecniche di debug di stampa di base. La classe Trace
si trova in System.Diagnostics
e usa classi di System.IO
come StreamWriter
.
Per iniziare, aggiungere le direttive
using
in cima a CalculatorLibrary.cs:// CalculatorLibrary.cs using System.Diagnostics;
Questo utilizzo della classe
Trace
deve contenere un riferimento per la classe associata a un filestream. Questo requisito indica che il calcolatore funziona meglio come oggetto, quindi aggiungere un costruttore all'inizio della classeCalculator
in CalculatorLibrary.cs.Rimuovere anche la parola chiave
static
per modificare il metodoDoOperation
statico in un metodo membro.// CalculatorLibrary.cs public Calculator() { StreamWriter logFile = File.CreateText("calculator.log"); Trace.Listeners.Add(new TextWriterTraceListener(logFile)); Trace.AutoFlush = true; Trace.WriteLine("Starting Calculator Log"); Trace.WriteLine(String.Format("Started {0}", System.DateTime.Now.ToString())); } public double DoOperation(double num1, double num2, string op) {
Aggiungere l'output del log a ogni calcolo.
DoOperation
dovrebbe ora essere simile al codice seguente:// CalculatorLibrary.cs public double DoOperation(double num1, double num2, string op) { double result = double.NaN; // Default value is "not-a-number" if an operation, such as division, could result in an error. // Use a switch statement to do the math. switch (op) { case "a": result = num1 + num2; Trace.WriteLine(String.Format("{0} + {1} = {2}", num1, num2, result)); break; case "s": result = num1 - num2; Trace.WriteLine(String.Format("{0} - {1} = {2}", num1, num2, result)); break; case "m": result = num1 * num2; Trace.WriteLine(String.Format("{0} * {1} = {2}", num1, num2, result)); break; case "d": // Ask the user to enter a non-zero divisor. if (num2 != 0) { result = num1 / num2; Trace.WriteLine(String.Format("{0} / {1} = {2}", num1, num2, result)); } break; // Return text for an incorrect option entry. default: break; } return result; }
Tornando su Program.cs, ora una sottolineatura ondulata rossa contrassegna la chiamata statica. Per correggere l'errore, creare una variabile
calculator
aggiungendo la riga di codice seguente subito prima del ciclowhile (!endApp)
:// Program.cs Calculator calculator = new Calculator();
Modificare anche il sito di chiamata
DoOperation
per fare riferimento all'oggetto denominatocalculator
in lettere minuscole. Il codice è ora una chiamata membro, anziché una chiamata a un metodo statico.// Program.cs result = calculator.DoOperation(cleanNum1, cleanNum2, op);
Eseguire di nuovo l'app. Al termine, fare clic con il pulsante destro del mouse sul nodo del progetto Calcolatrice e scegliere Apri cartella in Esplora File.
In Esplora file passare alla cartella di output in bin/Debug/e aprire il file calculator.log. L'output dovrebbe essere simile al seguente:
Starting Calculator Log Started 7/9/2020 1:58:19 PM 1 + 2 = 3 3 * 3 = 9
A questo punto, CalculatorLibrary.cs dovrebbe essere simile al codice seguente:
// CalculatorLibrary.cs
using System.Diagnostics;
namespace CalculatorLibrary
{
public class Calculator
{
public Calculator()
{
StreamWriter logFile = File.CreateText("calculator.log");
Trace.Listeners.Add(new TextWriterTraceListener(logFile));
Trace.AutoFlush = true;
Trace.WriteLine("Starting Calculator Log");
Trace.WriteLine(String.Format("Started {0}", System.DateTime.Now.ToString()));
}
public double DoOperation(double num1, double num2, string op)
{
double result = double.NaN; // Default value is "not-a-number" if an operation, such as division, could result in an error.
// Use a switch statement to do the math.
switch (op)
{
case "a":
result = num1 + num2;
Trace.WriteLine(String.Format("{0} + {1} = {2}", num1, num2, result));
break;
case "s":
result = num1 - num2;
Trace.WriteLine(String.Format("{0} - {1} = {2}", num1, num2, result));
break;
case "m":
result = num1 * num2;
Trace.WriteLine(String.Format("{0} * {1} = {2}", num1, num2, result));
break;
case "d":
// Ask the user to enter a non-zero divisor.
if (num2 != 0)
{
result = num1 / num2;
Trace.WriteLine(String.Format("{0} / {1} = {2}", num1, num2, result));
}
break;
// Return text for an incorrect option entry.
default:
break;
}
return result;
}
}
}
Program.cs dovrebbe essere simile al codice seguente:
// Program.cs
using CalculatorLibrary;
namespace CalculatorProgram
{
class Program
{
static void Main(string[] args)
{
bool endApp = false;
// Display title as the C# console calculator app.
Console.WriteLine("Console Calculator in C#\r");
Console.WriteLine("------------------------\n");
Calculator calculator = new Calculator();
while (!endApp)
{
// Declare variables and set to empty.
// Use Nullable types (with ?) to match type of System.Console.ReadLine
string? numInput1 = "";
string? numInput2 = "";
double result = 0;
// Ask the user to type the first number.
Console.Write("Type a number, and then press Enter: ");
numInput1 = Console.ReadLine();
double cleanNum1 = 0;
while (!double.TryParse(numInput1, out cleanNum1))
{
Console.Write("This is not valid input. Please enter an integer value: ");
numInput1 = Console.ReadLine();
}
// Ask the user to type the second number.
Console.Write("Type another number, and then press Enter: ");
numInput2 = Console.ReadLine();
double cleanNum2 = 0;
while (!double.TryParse(numInput2, out cleanNum2))
{
Console.Write("This is not valid input. Please enter an integer value: ");
numInput2 = Console.ReadLine();
}
// Ask the user to choose an operator.
Console.WriteLine("Choose an operator from the following list:");
Console.WriteLine("\ta - Add");
Console.WriteLine("\ts - Subtract");
Console.WriteLine("\tm - Multiply");
Console.WriteLine("\td - Divide");
Console.Write("Your option? ");
string? op = Console.ReadLine();
// Validate input is not null, and matches the pattern
if (op == null || ! Regex.IsMatch(op, "[a|s|m|d]"))
{
Console.WriteLine("Error: Unrecognized input.");
}
else
{
try
{
result = calculator.DoOperation(cleanNum1, cleanNum2, op);
if (double.IsNaN(result))
{
Console.WriteLine("This operation will result in a mathematical error.\n");
}
else Console.WriteLine("Your result: {0:0.##}\n", result);
}
catch (Exception e)
{
Console.WriteLine("Oh no! An exception occurred trying to do the math.\n - Details: " + e.Message);
}
}
Console.WriteLine("------------------------\n");
// Wait for the user to respond before closing.
Console.Write("Press 'n' and Enter to close the app, or press any other key and Enter to continue: ");
if (Console.ReadLine() == "n") endApp = true;
Console.WriteLine("\n"); // Friendly linespacing.
}
return;
}
}
}
Per eseguire operazioni di output in JSON, un formato diffuso e portabile per l'archiviazione dei dati degli oggetti, è possibile fare riferimento al pacchetto NuGet Newtonsoft. Json. I pacchetti NuGet sono il metodo di distribuzione principale per le librerie di classi .NET.
In Esplora soluzioni , fare clic con il pulsante destro del mouse sul nodo Dipendenze per il progetto CalculatorLibrary e scegliere Gestisci Pacchetti NuGet.
Si apre il Gestore pacchetti NuGet.
Cercare e selezionare il pacchetto Newtonsoft.Json, e selezionare Installa.
Visual Studio scarica il pacchetto e lo aggiunge al progetto. Viene visualizzata una nuova voce nel nodo Riferimenti in Esplora soluzioni .
Se viene richiesto se accettare le modifiche, selezionare OK.
Visual Studio scarica il pacchetto e lo aggiunge al progetto. Viene visualizzata una nuova voce nel nodo Pacchetti in Esplora soluzioni.
Aggiungere una direttiva
using
perNewtonsoft.Json
all'inizio di CalculatorLibrary.cs.// CalculatorLibrary.cs using Newtonsoft.Json;
Creare l'oggetto membro
JsonWriter
e sostituire il costruttoreCalculator
con il codice seguente:// CalculatorLibrary.cs JsonWriter writer; public Calculator() { StreamWriter logFile = File.CreateText("calculatorlog.json"); logFile.AutoFlush = true; writer = new JsonTextWriter(logFile); writer.Formatting = Formatting.Indented; writer.WriteStartObject(); writer.WritePropertyName("Operations"); writer.WriteStartArray(); }
Modificare il metodo
DoOperation
per aggiungere il codice jsonwriter
:// CalculatorLibrary.cs public double DoOperation(double num1, double num2, string op) { double result = double.NaN; // Default value is "not-a-number" if an operation, such as division, could result in an error. writer.WriteStartObject(); writer.WritePropertyName("Operand1"); writer.WriteValue(num1); writer.WritePropertyName("Operand2"); writer.WriteValue(num2); writer.WritePropertyName("Operation"); // Use a switch statement to do the math. switch (op) { case "a": result = num1 + num2; writer.WriteValue("Add"); break; case "s": result = num1 - num2; writer.WriteValue("Subtract"); break; case "m": result = num1 * num2; writer.WriteValue("Multiply"); break; case "d": // Ask the user to enter a non-zero divisor. if (num2 != 0) { result = num1 / num2; } writer.WriteValue("Divide"); break; // Return text for an incorrect option entry. default: break; } writer.WritePropertyName("Result"); writer.WriteValue(result); writer.WriteEndObject(); return result; }
Aggiungere un metodo per completare la sintassi JSON al termine dell'immissione dei dati dell'operazione da parte dell'utente.
// CalculatorLibrary.cs public void Finish() { writer.WriteEndArray(); writer.WriteEndObject(); writer.Close(); }
Alla fine di Program.cs, prima del
return;
, aggiungere una chiamata aFinish
:// Program.cs // Add call to close the JSON writer before return calculator.Finish(); return; }
Compilare ed eseguire l'app e dopo aver completato alcune operazioni, chiudere l'app immettendo il comando n.
Aprire il file calculatorlog.json in Esplora file. Verrà visualizzato un contenuto simile al seguente:
{ "Operations": [ { "Operand1": 2.0, "Operand2": 3.0, "Operation": "Add", "Result": 5.0 }, { "Operand1": 3.0, "Operand2": 4.0, "Operation": "Multiply", "Result": 12.0 } ] }
Il debugger di Visual Studio è uno strumento potente. Il debugger può eseguire il codice per trovare il punto esatto in cui si verifica un errore di programmazione. È quindi possibile comprendere quali correzioni è necessario apportare e apportare modifiche temporanee in modo da poter continuare a eseguire l'app.
In Program.cs, fare clic nel margine a sinistra della riga di codice seguente. È anche possibile fare clic nella riga e selezionare F9oppure fare clic con il pulsante destro del mouse sulla riga e selezionare punto di interruzione>Inserisci punto di interruzione.
// Program.cs result = calculator.DoOperation(cleanNum1, cleanNum2, op);
Il punto rosso visualizzato indica un punto di interruzione. Puoi usare i punti di interruzione per sospendere l'app ed esaminare il codice. È possibile impostare un punto di interruzione in qualsiasi riga di codice eseguibile.
Compilare ed eseguire l'app. Immettere i valori seguenti per il calcolo:
- Per il primo numero immettere 8.
- Per il secondo numero immettere 0.
- Per l'operatore, divertiamoci un po'. Immettere d.
L'app sospende dove è stato creato il punto di interruzione, indicato dal puntatore giallo a sinistra e dal codice evidenziato. Il codice evidenziato non è ancora stato eseguito.
Ora, con l'app sospesa, è possibile controllare lo stato dell'applicazione.
Nel codice evidenziato passare il puntatore del mouse sulle variabili, ad esempio
cleanNum1
eop
. I valori correnti per queste variabili, rispettivamente8
ed
, vengono visualizzati in Suggerimenti dati.Durante il debug, verificare se le variabili contengono i valori previsti è spesso fondamentale per risolvere i problemi.
Nel riquadro inferiore, guarda la finestra variabili locali. Se è chiuso, selezionare Debug>Windows>Locals per aprirlo.
La finestra variabili locali mostra ogni variabile attualmente nell'ambito, insieme al relativo valore e tipo.
Guardare la finestra Auto.
La finestra Auto è simile alla finestra variabili locali, ma mostra le variabili immediatamente precedenti e dopo la riga di codice corrente in cui l'app è sospesa.
Nota
Se non viene visualizzata la finestra Auto, selezionare Debug>Windows>Auto per aprirla.
Eseguire quindi il codice nel debugger un'istruzione alla volta, denominata istruzione.
Premere F11oppure selezionare Debug>Esegui istruzione.
Utilizzando il comando Passa all'interno, l'app esegue l'istruzione corrente e passa all'istruzione eseguibile successiva, solitamente la riga di codice successiva. Il puntatore giallo a sinistra indica sempre l'istruzione corrente.
È sufficiente passare al metodo
DoOperation
nella classeCalculator
.Per ottenere una visione gerarchica del flusso del programma, consulta la finestra Call Stack. Se è chiuso, selezionare Debug>Stack di chiamate di Windows> per aprirlo.
Questa visualizzazione mostra il metodo
Calculator.DoOperation
corrente, indicato dal puntatore giallo. La seconda riga mostra la funzione che ha chiamato il metodo , dal metodoMain
in Program.cs.La finestra stack di chiamate mostra l'ordine in cui vengono chiamati i metodi e le funzioni. Questa finestra consente anche l'accesso a molte funzionalità del debugger, ad esempio Vai al codice sorgente, dal relativo menu di scelta rapida.
Premere F10oppure selezionare Debug>Passa Sopra, più volte fino a quando l'app viene sospesa sull'istruzione
switch
.// CalculatorLibrary.cs switch (op) {
Il comando Step Over è simile al comando Step Into, ad eccezione del fatto che se l'istruzione corrente chiama una funzione, il debugger esegue il codice nella funzione e non sospende l'esecuzione fino a quando la funzione non viene restituita. Step Over è più veloce di Step Into se non si è interessati a una funzione particolare.
Premere F10 ancora una volta, in modo che l'app venga sospesa nella riga di codice seguente.
// CalculatorLibrary.cs if (num2 != 0) {
Questo codice verifica la presenza di un caso di divisione per zero. Se l'app continua, genera un'eccezione generale (un errore), ma potrebbe essere necessario provare qualcos'altro, ad esempio visualizzare il valore restituito effettivo nella console. Un'opzione consiste nell'usare una funzionalità del debugger denominata di modifica e continuazione per apportare modifiche al codice e quindi continuare il debug. Tuttavia, esiste un altro trucco per modificare temporaneamente il flusso di esecuzione.
Selezionare il puntatore giallo, attualmente sospeso nell'istruzione
if (num2 != 0)
e trascinarlo nell'istruzione seguente:// CalculatorLibrary.cs result = num1 / num2;
Se si trascina il puntatore, l'app ignora completamente l'istruzione
if
, quindi è possibile vedere cosa accade quando si divide per zero.Premere F10 per eseguire la riga di codice.
Se si passa il puntatore del mouse sulla variabile
result
, viene visualizzato il valore Infinity. In C#, Infinity è il risultato quando si divide per zero.Premere F5oppure selezionare Debug>Continua il debug.
Il simbolo infinito viene visualizzato nella console come risultato dell'operazione matematica.
Chiudere correttamente l'app immettendo il comando n.
Ecco il codice completo per il file CalculatorLibrary.cs, dopo aver completato tutti i passaggi:
// CalculatorLibrary.cs
using System;
using System.IO;
using Newtonsoft.Json;
namespace CalculatorLibrary
{
public class Calculator
{
JsonWriter writer;
public Calculator()
{
StreamWriter logFile = File.CreateText("calculatorlog.json");
logFile.AutoFlush = true;
writer = new JsonTextWriter(logFile);
writer.Formatting = Formatting.Indented;
writer.WriteStartObject();
writer.WritePropertyName("Operations");
writer.WriteStartArray();
}
public double DoOperation(double num1, double num2, string op)
{
double result = double.NaN; // Default value is "not-a-number" if an operation, such as division, could result in an error.
writer.WriteStartObject();
writer.WritePropertyName("Operand1");
writer.WriteValue(num1);
writer.WritePropertyName("Operand2");
writer.WriteValue(num2);
writer.WritePropertyName("Operation");
// Use a switch statement to do the math.
switch (op)
{
case "a":
result = num1 + num2;
writer.WriteValue("Add");
break;
case "s":
result = num1 - num2;
writer.WriteValue("Subtract");
break;
case "m":
result = num1 * num2;
writer.WriteValue("Multiply");
break;
case "d":
// Ask the user to enter a non-zero divisor.
if (num2 != 0)
{
result = num1 / num2;
}
writer.WriteValue("Divide");
break;
// Return text for an incorrect option entry.
default:
break;
}
writer.WritePropertyName("Result");
writer.WriteValue(result);
writer.WriteEndObject();
return result;
}
public void Finish()
{
writer.WriteEndArray();
writer.WriteEndObject();
writer.Close();
}
}
}
Ecco il codice per Program.cs:
// Program.cs
using System;
using CalculatorLibrary;
namespace CalculatorProgram
{
class Program
{
static void Main(string[] args)
{
bool endApp = false;
// Display title as the C# console calculator app.
Console.WriteLine("Console Calculator in C#\r");
Console.WriteLine("------------------------\n");
Calculator calculator = new Calculator();
while (!endApp)
{
// Declare variables and set to empty.
string numInput1 = "";
string numInput2 = "";
double result = 0;
// Ask the user to type the first number.
Console.Write("Type a number, and then press Enter: ");
numInput1 = Console.ReadLine();
double cleanNum1 = 0;
while (!double.TryParse(numInput1, out cleanNum1))
{
Console.Write("This is not valid input. Please enter an integer value: ");
numInput1 = Console.ReadLine();
}
// Ask the user to type the second number.
Console.Write("Type another number, and then press Enter: ");
numInput2 = Console.ReadLine();
double cleanNum2 = 0;
while (!double.TryParse(numInput2, out cleanNum2))
{
Console.Write("This is not valid input. Please enter an integer value: ");
numInput2 = Console.ReadLine();
}
// Ask the user to choose an operator.
Console.WriteLine("Choose an operator from the following list:");
Console.WriteLine("\ta - Add");
Console.WriteLine("\ts - Subtract");
Console.WriteLine("\tm - Multiply");
Console.WriteLine("\td - Divide");
Console.Write("Your option? ");
string op = Console.ReadLine();
try
{
result = calculator.DoOperation(cleanNum1, cleanNum2, op);
if (double.IsNaN(result))
{
Console.WriteLine("This operation will result in a mathematical error.\n");
}
else Console.WriteLine("Your result: {0:0.##}\n", result);
}
catch (Exception e)
{
Console.WriteLine("Oh no! An exception occurred trying to do the math.\n - Details: " + e.Message);
}
Console.WriteLine("------------------------\n");
// Wait for the user to respond before closing.
Console.Write("Press 'n' and Enter to close the app, or press any other key and Enter to continue: ");
if (Console.ReadLine() == "n") endApp = true;
Console.WriteLine("\n"); // Friendly linespacing.
}
calculator.Finish();
return;
}
}
}
Ecco il codice completo per il file CalculatorLibrary.cs, dopo aver completato tutti i passaggi:
// CalculatorLibrary.cs
using Newtonsoft.Json;
namespace CalculatorLibrary
{
public class Calculator
{
JsonWriter writer;
public Calculator()
{
StreamWriter logFile = File.CreateText("calculatorlog.json");
logFile.AutoFlush = true;
writer = new JsonTextWriter(logFile);
writer.Formatting = Formatting.Indented;
writer.WriteStartObject();
writer.WritePropertyName("Operations");
writer.WriteStartArray();
}
public double DoOperation(double num1, double num2, string op)
{
double result = double.NaN; // Default value is "not-a-number" if an operation, such as division, could result in an error.
writer.WriteStartObject();
writer.WritePropertyName("Operand1");
writer.WriteValue(num1);
writer.WritePropertyName("Operand2");
writer.WriteValue(num2);
writer.WritePropertyName("Operation");
// Use a switch statement to do the math.
switch (op)
{
case "a":
result = num1 + num2;
writer.WriteValue("Add");
break;
case "s":
result = num1 - num2;
writer.WriteValue("Subtract");
break;
case "m":
result = num1 * num2;
writer.WriteValue("Multiply");
break;
case "d":
// Ask the user to enter a non-zero divisor.
if (num2 != 0)
{
result = num1 / num2;
}
writer.WriteValue("Divide");
break;
// Return text for an incorrect option entry.
default:
break;
}
writer.WritePropertyName("Result");
writer.WriteValue(result);
writer.WriteEndObject();
return result;
}
public void Finish()
{
writer.WriteEndArray();
writer.WriteEndObject();
writer.Close();
}
}
}
Ecco il codice per Program.cs:
// Program.cs
using CalculatorLibrary;
namespace CalculatorProgram
{
class Program
{
static void Main(string[] args)
{
bool endApp = false;
// Display title as the C# console calculator app.
Console.WriteLine("Console Calculator in C#\r");
Console.WriteLine("------------------------\n");
Calculator calculator = new Calculator();
while (!endApp)
{
// Declare variables and set to empty.
// Use Nullable types (with ?) to match type of System.Console.ReadLine
string? numInput1 = "";
string? numInput2 = "";
double result = 0;
// Ask the user to type the first number.
Console.Write("Type a number, and then press Enter: ");
numInput1 = Console.ReadLine();
double cleanNum1 = 0;
while (!double.TryParse(numInput1, out cleanNum1))
{
Console.Write("This is not valid input. Please enter an integer value: ");
numInput1 = Console.ReadLine();
}
// Ask the user to type the second number.
Console.Write("Type another number, and then press Enter: ");
numInput2 = Console.ReadLine();
double cleanNum2 = 0;
while (!double.TryParse(numInput2, out cleanNum2))
{
Console.Write("This is not valid input. Please enter an integer value: ");
numInput2 = Console.ReadLine();
}
// Ask the user to choose an operator.
Console.WriteLine("Choose an operator from the following list:");
Console.WriteLine("\ta - Add");
Console.WriteLine("\ts - Subtract");
Console.WriteLine("\tm - Multiply");
Console.WriteLine("\td - Divide");
Console.Write("Your option? ");
string? op = Console.ReadLine();
// Validate input is not null, and matches the pattern
if (op == null || ! Regex.IsMatch(op, "[a|s|m|d]"))
{
Console.WriteLine("Error: Unrecognized input.");
}
else
{
try
{
result = calculator.DoOperation(cleanNum1, cleanNum2, op);
if (double.IsNaN(result))
{
Console.WriteLine("This operation will result in a mathematical error.\n");
}
else Console.WriteLine("Your result: {0:0.##}\n", result);
}
catch (Exception e)
{
Console.WriteLine("Oh no! An exception occurred trying to do the math.\n - Details: " + e.Message);
}
}
Console.WriteLine("------------------------\n");
// Wait for the user to respond before closing.
Console.Write("Press 'n' and Enter to close the app, or press any other key and Enter to continue: ");
if (Console.ReadLine() == "n") endApp = true;
Console.WriteLine("\n"); // Friendly linespacing.
}
calculator.Finish();
return;
}
}
}
Congratulazioni per aver completato questa esercitazione. Per altre informazioni, continuare con il contenuto seguente:
- Continuare con altre esercitazioni su C#
- Avvio rapido di : Creare un'app Web ASP.NET Core
- Informazioni su come eseguire il debug del codice C# in Visual Studio
- Procedura dettagliata per creare ed eseguire unit test
- Eseguire un programma C#
- Informazioni su IntelliSense C#
- Continuare con la panoramica dell'IDE di Visual Studio
- registrazione e tracciamento