Lernprogramm: Erweitern der C#-Konsolen-App und Debuggen in Visual Studio (Teil 2 von 2)
In Teil 2 dieser Lernprogrammreihe tauchen Sie etwas tiefer in die Visual Studio-Build- und Debugfeatures ein, die Sie für die tägliche Entwicklung benötigen. Diese Features umfassen das Verwalten mehrerer Projekte, das Debuggen und verweisen auf Drittanbieterpakete. Sie führen die C#-Konsolen-App aus, die Sie in Teil 1 dieses Lernprogrammserstellt haben, und erkunden Einige Features der integrierten Entwicklungsumgebung (IDE) von Visual Studio. Dieses Lernprogramm ist Teil 2 einer zweiteiligen Lernprogrammreihe.
In diesem Lernprogramm führen Sie die folgenden Aufgaben aus:
- Fügen Sie ein zweites Projekt hinzu.
- Referenzbibliotheken und Hinzufügen von Paketen.
- Debuggen Sie Ihren Code.
- Überprüfen des fertiggestellten Codes.
Voraussetzungen
Wenn Sie diesen Artikel durcharbeiten möchten, können Sie eine der folgenden Rechner-Apps verwenden:
- Die Rechnerkonsolen-App aus Teil 1 dieses Lernprogramms.
- Die C#-Rechner-App im Repository vs-tutorial-samples. Öffnen Sie als ersten Schritt die App aus dem Repository.
Hinzufügen eines weiteren Projekts
In der Praxis umfasst Code Projekte, die in einer Projektmappe zusammenarbeiten. Sie können Ihrer Rechner-App ein Klassenbibliotheksprojekt hinzufügen, das einige Rechnerfunktionen bereitstellt.
In Visual Studio verwenden Sie den Menübefehl Datei>Hinzufügen>Neues Projekt, um ein neues Projekt hinzuzufügen. Sie können auch mit der rechten Maustaste auf die Lösung im Lösungs-Explorer klicken, um ein Projekt aus dem Kontextmenü hinzuzufügen.
Klicken Sie im Projektmappen-Explorermit der rechten Maustaste auf den Lösungsknoten und wählen Sie Hinzufügen>Neues Projektaus.
Geben Sie auf im Fenster Neues Projekt hinzufügen class library (Klassenbibliothek) in das Suchfeld ein. Wählen Sie die C#-Klassenbibliothek Projektvorlage aus, und wählen Sie dann Nextaus.
Geben Sie auf dem Bildschirm Konfigurieren des neuen Projekts den Projektnamen CalculatorLibraryein, und wählen Sie dann Nextaus.
Wählen Sie .NET 3.1 aus, wenn Sie gefragt werden. Visual Studio erstellt das neue Projekt und fügt es zur Projektmappe hinzu.
Benennen Sie die Class1.cs-Datei in CalculatorLibrary.csum. Um die Datei umzubenennen, können Sie im Projektmappen-Explorer mit der rechten Maustaste auf den Namen klicken und Umbenennenauswählen, den Namen auswählen und F2drücken oder den Namen auswählen und erneut zum Eingeben auswählen.
Eine Nachricht fragt möglicherweise, ob Sie Verweise auf
Class1
in der Datei umbenennen möchten. Es spielt keine Rolle, wie Sie antworten, da Sie den Code in einem zukünftigen Schritt ersetzen.Fügen Sie nun einen Projektverweis hinzu, sodass das erste Projekt APIs verwenden kann, die die neue Klassenbibliothek verfügbar macht. Klicken Sie mit der rechten Maustaste im ersten Projekt auf den Knoten Abhängigkeiten im Calculator-Projekt, und wählen Sie Projektverweis hinzufügen aus.
Das Dialogfeld Verweis-Manager wird angezeigt. In diesem Dialogfeld können Sie Verweise auf andere Projekte, Assemblys und COM-DLLs hinzufügen, die Ihre Projekte benötigen.
Aktivieren Sie im Dialogfeld Verweis-Manager das Kontrollkästchen für das Projekt CalculatorLibrary, und wählen Sie dann OK aus.
Der Projektverweis wird unter dem Knoten Projekte im Projektmappen-Explorer angezeigt.
Wählen Sie in Program.csdie
Calculator
Klasse und den gesamten Code aus, und drücken Sie STRG+X-, um sie auszuschneiden. Fügen Sie dann in CalculatorLibrary.csden Code in denCalculatorLibrary
Namespace ein.Fügen Sie außerdem
public
vor der Rechnerklasse hinzu, um sie außerhalb der Bibliothek verfügbar zu machen.CalculatorLibrary.cs sollte nun dem folgenden Code ähneln:
// 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 verfügt ebenfalls über einen Verweis, ein Fehler meldet jedoch, dass der
Calculator.DoOperation
-Aufruf nicht aufgelöst wird. Der Fehler liegt daran, dassCalculatorLibrary
sich in einem anderen Namespace befindet. Für einen vollqualifizierten Verweis können Sie in Program.cs demCalculator.DoOperation
-Aufruf denCalculatorLibrary
-Namespace hinzufügen:// Program.cs result = CalculatorLibrary.Calculator.DoOperation(cleanNum1, cleanNum2, op);
Oder Sie können versuchen, eine
using
Direktive am Anfang der Program.cs Datei hinzuzufügen:// Program.cs using CalculatorLibrary;
Durch das Hinzufügen der
using
-Anweisung sollten Sie denCalculatorLibrary
-Namespace aus der Aufrufsite entfernen können, jedoch liegt nun eine Mehrdeutigkeit vor. IstCalculator
die Klasse inCalculatorLibrary
, oder istCalculator
der Namespace?Um die Mehrdeutigkeit zu beheben, benennen Sie in Program.csden Namespace von
Calculator
inCalculatorProgram
um.// Program.cs namespace CalculatorProgram
Klicken Sie im Lösungs-Explorermit der rechten Maustaste auf den Lösungsknoten, und wählen Sie Hinzufügen>Neues Projektaus.
Geben Sie auf im Fenster Neues Projekt hinzufügen class library (Klassenbibliothek) in das Suchfeld ein. Wählen Sie die C#-Klassenbibliothek Projektvorlage aus, und wählen Sie dann Nextaus.
Geben Sie auf dem Bildschirm Konfigurieren des neuen Projekts den Projektnamen CalculatorLibraryein, und wählen Sie dann Nextaus.
Auf dem Bildschirm Zusätzliche Informationen ist .NET 8.0 ausgewählt. Wählen Sie Erstellen aus.
Visual Studio erstellt das neue Projekt und fügt es zur Projektmappe hinzu.
Benennen Sie die Class1.cs-Datei in CalculatorLibrary.csum. Um die Datei umzubenennen, können Sie im Projektmappen-Explorer mit der rechten Maustaste auf den Namen klicken und Umbenennenauswählen, den Namen auswählen und F2drücken oder den Namen auswählen und erneut zum Eingeben auswählen.
Eine Nachricht fragt möglicherweise, ob Sie alle Verweise auf
Class1
in der Datei umbenennen möchten. Es spielt keine Rolle, wie Sie antworten, da Sie den Code in einem zukünftigen Schritt ersetzen.Fügen Sie nun einen Projektverweis hinzu, sodass das erste Projekt APIs verwenden kann, die die neue Klassenbibliothek verfügbar macht. Klicken Sie mit der rechten Maustaste im ersten Projekt auf den Knoten Abhängigkeiten im Calculator-Projekt, und wählen Sie Projektverweis hinzufügen aus.
Das Dialogfeld Verweis-Manager wird angezeigt. In diesem Dialogfeld können Sie Verweise auf andere Projekte, Assemblys und COM-DLLs hinzufügen, die Ihre Projekte benötigen.
Aktivieren Sie im Dialogfeld Verweis-Manager das Kontrollkästchen für das Projekt CalculatorLibrary, und wählen Sie dann OK aus.
Der Projektverweis wird unter dem Knoten Projekte im Projektmappen-Explorer angezeigt.
Wählen Sie in Program.csdie
Calculator
Klasse und den gesamten Code aus, und drücken Sie STRG+X-, um sie auszuschneiden. Fügen Sie dann in CalculatorLibrary.csden Code in denCalculatorLibrary
Namespace ein.Fügen Sie außerdem
public
vor der Rechnerklasse hinzu, um sie außerhalb der Bibliothek verfügbar zu machen.CalculatorLibrary.cs sollte nun dem folgenden Code ähneln:
// 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 verfügt ebenfalls über einen Verweis, ein Fehler meldet jedoch, dass der
Calculator.DoOperation
-Aufruf nicht aufgelöst wird. Der Fehler liegt daran, dassCalculatorLibrary
sich in einem anderen Namespace befindet. Für einen vollqualifizierten Verweis können Sie in Program.cs demCalculator.DoOperation
-Aufruf denCalculatorLibrary
-Namespace hinzufügen:// Program.cs result = CalculatorLibrary.Calculator.DoOperation(cleanNum1, cleanNum2, op);
Oder Sie können versuchen, eine
using
Direktive am Anfang der Program.cs Datei hinzuzufügen:// Program.cs using CalculatorLibrary;
Wenn Sie die
using
-Direktive hinzufügen, können Sie denCalculatorLibrary
-Namespace aus der Aufrufstelle entfernen.Wenn sich Ihr
Program.cs
Code imCalculator
Namespace befindet, benennen Sie den Namespace ausCalculator
inCalculatorProgram
um, um die Mehrdeutigkeit zwischen dem Klassennamen und dem Namen des Namespaces zu beseitigen.
Verweisen auf .NET-Bibliotheken: Schreiben in ein Protokoll
Sie können die .NET Trace Klasse verwenden, um ein Protokoll aller Vorgänge hinzuzufügen und in eine Textdatei zu schreiben. Die Trace
Klasse ist auch nützlich für grundlegende Druckdebuggingtechniken. Die Trace
Klasse befindet sich in System.Diagnostics
und verwendet System.IO
Klassen wie StreamWriter
.
Beginnen Sie, indem Sie die
using
Direktiven oben in CalculatorLibrary.cshinzufügen:// CalculatorLibrary.cs using System.IO; using System.Diagnostics;
Diese Verwendung der
Trace
Klasse muss einen Verweis für die Klasse enthalten, die sie einem Dateistream zuordnet. Diese Anforderung bedeutet, dass der Rechner besser als Objekt funktioniert. Fügen Sie also am Anfang derCalculator
Klasse in CalculatorLibrary.cseinen Konstruktor hinzu.Entfernen Sie außerdem das schlüsselwort
static
, um die statischeDoOperation
-Methode in eine Membermethode zu ändern.// 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) {
Fügen Sie jeder Berechnung Protokollausgabe hinzu.
DoOperation
sollte nun wie der folgende Code aussehen:// 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; }
Zurück in Program.cs kennzeichnet nun eine rote Schlangenlinie den statischen Aufruf. Um den Fehler zu beheben, erstellen Sie eine
calculator
Variable, indem Sie die folgende Codezeile direkt vor derwhile (!endApp)
Schleife hinzufügen:// Program.cs Calculator calculator = new Calculator();
Ändern Sie außerdem die Aufrufstelle von
DoOperation
, um auf das Objekt mit dem in Kleinbuchstaben geschriebenen Namencalculator
zu verweisen. Der Code ist jetzt ein Mitgliedsaufruf, anstatt ein Aufruf einer statischen Methode.// Program.cs result = calculator.DoOperation(cleanNum1, cleanNum2, op);
Führen Sie die App erneut aus. Wenn Sie fertig sind, klicken Sie mit der rechten Maustaste auf den Projektknoten Calculator, und wählen Sie Ordner im Datei-Explorer öffnen aus.
Navigieren Sie im Datei-Explorer zu dem Ausgabeordner unter bin/Debug/net8.0 (oder einer beliebigen .NET-Version), und öffnen Sie die calculator.log Datei. Die Ausgabe sollte etwa wie folgt aussehen:
Starting Calculator Log Started 7/9/2020 1:58:19 PM 1 + 2 = 3 3 * 3 = 9
An diesem Punkt sollte CalculatorLibrary.cs diesem Code ähneln:
// 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 sollte wie der folgende Code aussehen:
// 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;
}
}
}
Sie können die .NET Trace Klasse verwenden, um ein Protokoll aller Vorgänge hinzuzufügen und in eine Textdatei zu schreiben. Die Trace
Klasse ist auch nützlich für grundlegende Druckdebuggingtechniken. Die Trace
Klasse befindet sich in System.Diagnostics
und verwendet System.IO
Klassen wie StreamWriter
.
Beginnen Sie, indem Sie die
using
Direktiven oben in CalculatorLibrary.cshinzufügen:// CalculatorLibrary.cs using System.Diagnostics;
Diese Verwendung der
Trace
Klasse muss einen Verweis für die Klasse enthalten, die sie einem Dateistream zuordnet. Diese Anforderung bedeutet, dass der Rechner besser als Objekt funktioniert. Fügen Sie also am Anfang derCalculator
Klasse in CalculatorLibrary.cseinen Konstruktor hinzu.Entfernen Sie außerdem das schlüsselwort
static
, um die statischeDoOperation
-Methode in eine Membermethode zu ändern.// 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) {
Fügen Sie jeder Berechnung Protokollausgabe hinzu.
DoOperation
sollte nun wie der folgende Code aussehen:// 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; }
Zurück in Program.cs kennzeichnet nun eine rote Schlangenlinie den statischen Aufruf. Um den Fehler zu beheben, erstellen Sie eine
calculator
Variable, indem Sie die folgende Codezeile direkt vor derwhile (!endApp)
Schleife hinzufügen:// Program.cs Calculator calculator = new Calculator();
Ändern Sie außerdem die Aufrufstelle
DoOperation
, um auf das Objekt mit dem Namencalculator
in Kleinbuchstaben zu verweisen. Der Code ist jetzt ein Memberaufruf anstelle des Aufrufs einer statischen Methode.// Program.cs result = calculator.DoOperation(cleanNum1, cleanNum2, op);
Führen Sie die App erneut aus. Wenn Sie fertig sind, klicken Sie mit der rechten Maustaste auf den Projektknoten Calculator, und wählen Sie Ordner im Datei-Explorer öffnen aus.
Navigieren Sie im Datei-Explorer unter bin/Debug/zum Ausgabeordner, und öffnen Sie die calculator.log Datei. Die Ausgabe sollte etwa wie folgt aussehen:
Starting Calculator Log Started 7/9/2020 1:58:19 PM 1 + 2 = 3 3 * 3 = 9
An diesem Punkt sollte CalculatorLibrary.cs diesem Code ähneln:
// 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 sollte wie der folgende Code aussehen:
// 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;
}
}
}
Hinzufügen eines NuGet-Pakets: Schreiben in eine JSON-Datei
Zum Ausgeben von Vorgängen in JSON, einem beliebten und tragbaren Format zum Speichern von Objektdaten, können Sie auf das Newtonsoft.Json NuGet-Paket verweisen. NuGet-Pakete sind die primäre Verteilungsmethode für .NET-Klassenbibliotheken.
Klicken Sie im Projektmappen-Explorer mit der rechten Maustaste für das Projekt CalculatorLibrary auf den Knoten Abhängigkeiten, und wählen Sie dann NuGet-Pakete verwalten aus.
Der NuGet-Paket-Manager wird geöffnet.
Suchen Sie nach dem Paket Newtonsoft.json, wählen Sie es aus, und wählen Sie dann Installieren aus.
Visual Studio lädt das Paket herunter und fügt es dem Projekt hinzu. Ein neuer Eintrag wird im Knoten „Verweise“ im Projektmappen-Explorer angezeigt.
Wenn Sie gefragt werden, ob Änderungen akzeptiert werden sollen, wählen Sie OKaus.
Visual Studio lädt das Paket herunter und fügt es dem Projekt hinzu. Ein neuer Eintrag wird im Projektmappen-Explorer in einem Knoten Pakete angezeigt.
Fügen Sie eine
using
-Direktive fürNewtonsoft.Json
am Anfang von CalculatorLibrary.cshinzu.// CalculatorLibrary.cs using Newtonsoft.Json;
Erstellen Sie das
JsonWriter
Memberobjekt, und ersetzen Sie denCalculator
-Konstruktor durch den folgenden Code:// 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(); }
Ändern Sie die
DoOperation
-Methode, um den JSON-writer
Code hinzuzufügen:// 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; }
Fügen Sie eine Methode hinzu, um die JSON-Syntax abzuschließen, sobald der Benutzer die Eingabe von Vorgangsdaten abgeschlossen hat.
// CalculatorLibrary.cs public void Finish() { writer.WriteEndArray(); writer.WriteEndObject(); writer.Close(); }
Fügen Sie am Ende von Program.cs vor
return;
einenFinish
-Aufruf hinzu:// Program.cs // Add call to close the JSON writer before return calculator.Finish(); return; }
Erstellen Sie die App, und führen Sie sie aus, und schließen Sie die App, nachdem Sie einige Vorgänge eingegeben haben, indem Sie den Befehl n eingeben.
Öffnen Sie die calculatorlog.json Datei im Datei-Explorer. Sie sollten etwa den folgenden Inhalt sehen:
{ "Operations": [ { "Operand1": 2.0, "Operand2": 3.0, "Operation": "Add", "Result": 5.0 }, { "Operand1": 3.0, "Operand2": 4.0, "Operation": "Multiply", "Result": 12.0 } ] }
Debuggen: Festlegen und Erreichen eines Haltepunkts
Der Visual Studio-Debugger ist ein leistungsfähiges Tool. Der Debugger kann Ihren Code schrittweise durchlaufen, um den genauen Punkt zu finden, an dem ein Programmierfehler aufgetreten ist. Sie können dann verstehen, welche Korrekturen Sie vornehmen müssen, und temporäre Änderungen vornehmen, damit Sie die App weiterhin ausführen können.
Klicken Sie in Program.cs auf den Bundsteg links neben der folgenden Codezeile. Sie können auch in der Zeile klicken und F9 auswählen oder mit der rechten Maustaste auf die Zeile klicken und Breakpoint>Breakpoint einfügen auswählen.
// Program.cs result = calculator.DoOperation(cleanNum1, cleanNum2, op);
Der angezeigte rote Punkt weist auf einen Haltepunkt hin. Sie können Haltepunkte verwenden, um Ihre App anzuhalten und Code zu prüfen. Sie können einen Haltepunkt für jede ausführbare Codezeile festlegen.
Erstellen sie die App, und führen Sie sie aus. Geben Sie die folgenden Werte für die Berechnung ein:
- Geben Sie für die erste Zahl 8ein.
- Geben Sie für die zweite Zahl 0ein.
- Im folgenden Abschnitt wird der Operator veranschaulicht. Geben Sie dein.
Die App pausiert an der Position des Haltepunkts. Das ist am links angezeigten gelben Pfeil und am hervorgehobenen Code erkennbar. Der hervorgehobene Code wurde noch nicht ausgeführt.
Jetzt, da die App pausiert ist, können Sie den Anwendungsstatus überprüfen.
Debuggen: Anzeigen von Variablen
Fahren Sie im hervorgehobenen Code mit der Maus über Variablen wie
cleanNum1
undop
. Die aktuellen Werte für diese Variablen,8
bzw.d
, werden in DataTips angezeigt.Beim Debuggen ist die Überprüfung, ob Variablen die erwarteten Werte enthalten, häufig wichtig, um Probleme zu beheben.
Zeigen Sie im unteren Bereich das Fenster Lokal an. Wenn sie geschlossen ist, wählen Sie Debuggen>Windows>Locals aus, um es zu öffnen.
Im Fenster Lokale Variablen werden alle Variablen angezeigt, die sich derzeit im Bereich befinden, gemeinsam mit dem zugehörigen Wert und Typ.
Zeigen Sie das Fenster Auto an.
Das Fenster "Autos" ähnelt dem fenster Locals, zeigt jedoch die Variablen an, die unmittelbar vor und nach der aktuellen Codezeile folgen, in der Die App angehalten wird.
Anmerkung
Wenn das Fenster "Autos" nicht angezeigt wird, wählen Sie Debuggen>Windows>Autos aus, um es zu öffnen.
Nun führen Sie den Code im Debugger pro Anweisung aus. Dieses Vorgehen wird als Stepping bezeichnet.
Debuggen: Schrittweise durch den Code gehen
Drücken Sie F11, oder wählen Sie Debuggen>Einzelschritt aus.
Mithilfe des Befehls "Schritt in" führt die App die aktuelle Anweisung aus und wechselt zur nächsten ausführbaren Anweisung, in der Regel die nächste Codezeile. Der gelbe Zeiger auf der linken Seite gibt immer die aktuelle Anweisung an.
Sie haben soeben einen Einzelschritt in die Methode
DoOperation
der KlasseCalculator
ausgeführt.Um einen hierarchischen Blick auf Ihren Programmablauf zu erhalten, sehen Sie sich das Fenster Anrufstapel an. Wählen Sie Debuggen>Fenster>Aufrufliste aus, falls es nicht geöffnet ist.
In dieser Ansicht wird die aktuelle
Calculator.DoOperation
-Methode angezeigt, die durch den gelben Zeiger angegeben ist. Die zweite Zeile zeigt die Funktion, die die Methode aufgerufen hat, aus derMain
-Methode in Program.cs.Im Fenster Aufrufstapel- wird die Reihenfolge angezeigt, in der Methoden und Funktionen aufgerufen werden. Dieses Fenster bietet über das Kontextmenü ebenfalls Zugriff auf zahlreiche Debuggerfeatures wie Gehe zu Quellcode.
Drücken Sie wiederholt F10, oder wählen Sie Debuggen>Prozedurschritt aus, bis die App an der Anweisung
switch
angehalten wird.// CalculatorLibrary.cs switch (op) {
Der Befehl „Prozedurschritt“ ähnelt dem Befehl „Einzelschritt“, weist aber folgenden Unterschied auf: Wenn die aktuelle Anweisung eine Funktion aufruft, führt der Debugger den Code in der Funktion auf und hält die Ausführung erst an, wenn die Funktion zurückgegeben wird. Step Over ist schneller als Step Into, wenn Sie nicht an einer bestimmten Funktion interessiert sind.
Drücken Sie F10 ein weiteres Mal, sodass die App in der folgenden Codezeile angehalten wird.
// CalculatorLibrary.cs if (num2 != 0) {
Dieser Code überprüft, ob eine Division durch 0 durchgeführt wird. Wenn die App fortgesetzt wird, löst sie eine allgemeine Ausnahme (ein Fehler) aus, aber Sie können etwas anderes ausprobieren, z. B. den tatsächlich zurückgegebenen Wert in der Konsole anzeigen. Eine Option besteht darin, ein Debuggerfeature namens Edit-and-continue zu verwenden, um Änderungen am Code vorzunehmen und dann mit dem Debuggen fortzufahren. Es gibt jedoch einen anderen Trick, den Ausführungsfluss vorübergehend zu ändern.
Debuggen: Testen einer temporären Änderung
Wählen Sie den gelben Pfeil aus, der im angehaltenen Zustand aktuell auf die Anweisung
if (num2 != 0)
zeigt, und ziehen Sie ihn auf die folgende Anweisung:// CalculatorLibrary.cs result = num1 / num2;
Wenn Sie den Mauszeiger hier ziehen, überspringt die App die
if
Anweisung vollständig, sodass Sie sehen können, was passiert, wenn Sie durch Null dividieren.Drücken Sie F10-, um die Codezeile auszuführen.
Wenn Sie mit der Maus auf die
result
Variable zeigen, wird der Wert Infinityangezeigt. In C# ist Infinity das Ergebnis, wenn Sie durch Null dividieren.Drücken Sie F5, oder wählen Sie Debuggen>Debuggen fortsetzen aus.
Das Unendlichkeitssymbol wird in der Konsole als Ergebnis des mathematischen Vorgangs angezeigt.
Schließen Sie die App ordnungsgemäß, indem Sie den Befehl n eingeben.
Code fertiggestellt
Hier sehen Sie den vollständigen Code für die CalculatorLibrary.cs-Datei, nachdem Sie alle Schritte ausgeführt haben:
// 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();
}
}
}
Und hier ist der Code für 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;
}
}
}
Hier sehen Sie den vollständigen Code für die CalculatorLibrary.cs-Datei, nachdem Sie alle Schritte ausgeführt haben:
// 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();
}
}
}
Und hier ist der Code für 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;
}
}
}
Nächste Schritte
Herzlichen Glückwunsch zum Abschluss dieses Lernprogramms! Um mehr zu erfahren, fahren Sie mit den folgenden Inhalten fort:
- Fahren Sie mit weiteren C#-Tutorials fort
- Schnellstart: Erstellen einer ASP.NET Core Web App-
- Informationen zum Debuggen von C#-Code in Visual Studio
- Schritt-für-Schritt-Anleitung zum Erstellen und Ausführen von Unittests
- Ausführen eines C#-Programms
- Informationen zu C# IntelliSense-
- Weiter mit der Übersicht über die Visual Studio IDE
- Protokollierung und Ablaufverfolgung