Samouczek: rozszerzanie aplikacji konsolowej języka C# i debugowanie w programie Visual Studio (część 2 z 2)
W części 2 tej serii samouczków bardziej szczegółowo poznasz funkcje kompilacji i debugowania programu Visual Studio potrzebne do codziennego programowania. Te funkcje obejmują zarządzanie wieloma projektami, debugowaniem i odwoływaniem się do pakietów innych firm. Uruchom aplikację konsolową języka C# utworzoną w część 1 tego samouczkai zapoznasz się z niektórymi funkcjami zintegrowanego środowiska projektowego (IDE) programu Visual Studio. Ten samouczek jest częścią 2 dwuczęściowej serii samouczków.
W tym samouczku wykonasz następujące zadania:
- Dodaj drugi projekt.
- Biblioteki referencyjne i dodawanie pakietów.
- Debugowanie kodu.
- Sprawdź ukończony kod.
Warunki wstępne
Aby pracować z tym artykułem, możesz użyć jednej z następujących aplikacji kalkulatora:
- Aplikacja konsolowa kalkulatora z części 1 tego samouczka.
- Aplikacja kalkulatora w języku C# w repozytorium vs-tutorial-samples . Aby rozpocząć, otwórz aplikację z repozytorium.
Dodawanie innego projektu
Rzeczywisty kod obejmuje projekty współpracujące ze sobą w rozwiązaniu. Projekt biblioteki klas można dodać do aplikacji kalkulatora, która udostępnia niektóre funkcje kalkulatora.
W programie Visual Studio użyjesz polecenia menu Plik>Dodaj>Nowy projekt, aby dodać nowy projekt. Możesz również kliknąć rozwiązanie prawym przyciskiem myszy w eksploratorze rozwiązań , aby dodać projekt z menu kontekstowego.
W eksploratorze rozwiązań kliknij prawym przyciskiem myszy węzeł rozwiązania i wybierz Dodaj>Nowy projekt.
W oknie Dodaj nowy projekt wpisz biblioteka klas w polu wyszukiwania. Wybierz szablon projektu biblioteki klas języka C#, a następnie wybierz Dalej.
Na ekranie Konfigurowanie nowego projektu wpisz nazwę projektu CalculatorLibrary, a następnie wybierz Dalej.
Wybierz .NET 3.1, gdy zostaniesz o to poproszony. Program Visual Studio tworzy nowy projekt i dodaje go do rozwiązania.
Zmień nazwę pliku Class1.cs na CalculatorLibrary.cs. Aby zmienić nazwę pliku, możesz kliknąć prawym przyciskiem myszy nazwę w eksploratorze rozwiązań i wybrać Zmień nazwę, wybierz nazwę i naciśnij F2lub wybierz nazwę i wybierz ponownie, aby wpisać.
Komunikat może zapytać, czy chcesz zmienić nazwy odwołań na
Class1
w pliku. Nie ma znaczenia, jak odpowiadasz, ponieważ zastąpisz kod w przyszłym kroku.Teraz dodaj odwołanie do projektu, aby pierwszy projekt mógł używać interfejsów API udostępnianych przez nową bibliotekę klas. Kliknij prawym przyciskiem myszy węzeł zależności w projekcie Kalkulator i wybierz pozycję Dodaj odwołanie do projektu.
Zostanie wyświetlone okno dialogowe Menedżera odwołań. W tym oknie dialogowym można dodawać odwołania do innych projektów, zestawów i bibliotek DLL com potrzebnych w projektach.
W oknie dialogowym Reference Manager zaznacz pole wyboru projektu CalculatorLibrary, a następnie wybierz pozycję OK.
Odwołanie do projektu jest wyświetlane w węźle Projects w Eksploratorze Rozwiązań .
W Program.cswybierz klasę
Calculator
i cały kod, a następnie naciśnij Ctrl+X, aby go wyciąć. Następnie w CalculatorLibrary.cswklej kod do przestrzeni nazwCalculatorLibrary
.Dodaj również
public
przed klasą Calculator, aby udostępnić ją poza biblioteką.CalculatorLibrary.cs powinny teraz wyglądać podobnie do następującego kodu:
// 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 również ma odwołanie, ale występuje błąd, który wskazuje, że wywołanie
Calculator.DoOperation
nie zostało rozwiązane. Błąd jest spowodowany tym, żeCalculatorLibrary
znajduje się w innej przestrzeni nazw. W przypadku w pełni kwalifikowanej referencji można dodać przestrzeń nazwCalculatorLibrary
do wywołaniaCalculator.DoOperation
w Program.cs:// Program.cs result = CalculatorLibrary.Calculator.DoOperation(cleanNum1, cleanNum2, op);
Możesz też spróbować dodać dyrektywę
using
na początku pliku Program.cs:// Program.cs using CalculatorLibrary;
Dodanie dyrektywy
using
może usunąć przestrzeń nazwCalculatorLibrary
z miejsca wywołania, ale teraz istnieje niejednoznaczność. CzyCalculator
to klasa wCalculatorLibrary
, czyCalculator
to przestrzeń nazw?Aby rozwiązać niejednoznaczność, zmień nazwę przestrzeni nazw z
Calculator
naCalculatorProgram
w Program.cs.// Program.cs namespace CalculatorProgram
W eksploratorze rozwiązań kliknij prawym przyciskiem myszy węzeł rozwiązania i wybierz Dodaj>Nowy projekt.
W oknie Dodaj nowy projekt wpisz biblioteka klas w polu wyszukiwania. Wybierz szablon projektu biblioteki klas języka C#, a następnie wybierz Dalej.
Na ekranie Konfigurowanie nowego projektu wpisz nazwę projektu CalculatorLibrary, a następnie wybierz Dalej.
Na ekranie Dodatkowe informacje jest wybrana opcja .NET 8.0. Wybierz pozycję Utwórz.
Program Visual Studio tworzy nowy projekt i dodaje go do rozwiązania.
Zmień nazwę pliku Class1.cs na CalculatorLibrary.cs. Aby zmienić nazwę pliku, możesz kliknąć prawym przyciskiem myszy nazwę w eksploratorze rozwiązań i wybrać Zmień nazwę, wybierz nazwę i naciśnij F2lub wybierz nazwę i wybierz ponownie, aby wpisać.
Komunikat może zapytać, czy chcesz zmienić nazwę wszystkich odwołań na
Class1
w pliku. Nie ma znaczenia, jak odpowiadasz, ponieważ zastąpisz kod w przyszłym kroku.Teraz dodaj odwołanie do projektu, aby pierwszy projekt mógł używać interfejsów API udostępnianych przez nową bibliotekę klas. Kliknij prawym przyciskiem myszy węzeł zależności w projekcie Kalkulator i wybierz pozycję Dodaj odwołanie do projektu.
Zostanie wyświetlone okno dialogowe Menedżera odwołań. W tym oknie dialogowym można dodawać odwołania do innych projektów, zestawów i bibliotek DLL com potrzebnych w projektach.
W oknie dialogowym Reference Manager zaznacz pole wyboru projektu CalculatorLibrary, a następnie wybierz pozycję OK.
Odwołanie do projektu jest wyświetlane w węźle Projects w Eksploratorze Rozwiązań .
W Program.cswybierz klasę
Calculator
i cały kod, a następnie naciśnij Ctrl+X, aby go wyciąć. Następnie w CalculatorLibrary.cswklej kod do przestrzeni nazwCalculatorLibrary
.Dodaj również
public
przed klasą Calculator, aby udostępnić ją poza biblioteką.CalculatorLibrary.cs powinny teraz wyglądać podobnie do następującego kodu:
// 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 również ma odwołanie, ale występuje błąd, który wskazuje, że wywołanie
Calculator.DoOperation
nie zostało rozwiązane. Błąd jest spowodowany tym, żeCalculatorLibrary
znajduje się w innej przestrzeni nazw. W przypadku w pełni kwalifikowanej referencji można dodać przestrzeń nazwCalculatorLibrary
do wywołaniaCalculator.DoOperation
w Program.cs:// Program.cs result = CalculatorLibrary.Calculator.DoOperation(cleanNum1, cleanNum2, op);
Możesz też spróbować dodać dyrektywę
using
na początku pliku Program.cs:// Program.cs using CalculatorLibrary;
Dodanie dyrektywy
using
powinno umożliwić usunięcie przestrzeni nazwCalculatorLibrary
z miejsca wywołania.Jeśli kod
Program.cs
znajduje się w przestrzeni nazwCalculator
, zmień nazwę przestrzeni nazw zCalculator
naCalculatorProgram
, aby usunąć niejednoznaczność między nazwą klasy a nazwą przestrzeni nazw.
Biblioteki referencyjne .NET: Zapisywanie do logu
Możesz użyć klasy trace .NET, aby dodać dziennik wszystkich operacji i zapisać go w pliku tekstowym. Klasa Trace
jest również przydatna w przypadku podstawowych technik debugowania wydruku. Klasa Trace
znajduje się w System.Diagnostics
i używa klas System.IO
, takich jak StreamWriter
.
Zacznij od dodania dyrektyw
using
w górnej części CalculatorLibrary.cs:// CalculatorLibrary.cs using System.IO; using System.Diagnostics;
To użycie klasy
Trace
musi zawierać odwołanie do klasy, którą kojarzy z strumieniem plików. To wymaganie oznacza, że kalkulator działa lepiej jako obiekt, dlatego dodaj konstruktor na początku klasyCalculator
w CalculatorLibrary.cs.Usuń także słowo kluczowe
static
, aby przekształcić metodę statycznąDoOperation
w metodę składową.// 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) {
Dodaj dane wyjściowe dziennika do każdego obliczenia.
DoOperation
powinien teraz wyglądać podobnie do następującego kodu:// 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; }
Powrót do Program.cs, czerwone faliste podkreślenie teraz wskazuje na wywołanie statyczne. Aby rozwiązać ten problem, utwórz zmienną
calculator
, dodając następujący wiersz kodu tuż przed pętląwhile (!endApp)
:// Program.cs Calculator calculator = new Calculator();
Zmodyfikuj również lokację wywołania
DoOperation
, aby odwoływać się do obiektu o nazwiecalculator
małymi literami. Kod jest teraz wywołaniem elementu członkowskiego, a nie wywołaniem metody statycznej.// Program.cs result = calculator.DoOperation(cleanNum1, cleanNum2, op);
Ponownie uruchom aplikację. Po zakończeniu kliknij prawym przyciskiem myszy węzeł projektu Kalkulator i wybierz "Otwórz folder w Eksploratorze plików" .
W Eksploratorze plików przejdź do folderu wyjściowego w obszarze bin/Debug/net8.0 (lub dowolnej używanej wersji platformy .NET) i otwórz plik calculator.log. Dane wyjściowe powinny wyglądać mniej więcej tak:
Starting Calculator Log Started 7/9/2020 1:58:19 PM 1 + 2 = 3 3 * 3 = 9
W tym momencie CalculatorLibrary.cs powinny wyglądać podobnie do tego kodu:
// 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 powinien wyglądać podobnie do następującego kodu:
// 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;
}
}
}
Możesz użyć klasy trace .NET, aby dodać dziennik wszystkich operacji i zapisać go w pliku tekstowym. Klasa Trace
jest również przydatna w przypadku podstawowych technik debugowania wydruku. Klasa Trace
znajduje się w System.Diagnostics
i używa klas System.IO
, takich jak StreamWriter
.
Zacznij od dodania dyrektyw
using
w górnej części CalculatorLibrary.cs:// CalculatorLibrary.cs using System.Diagnostics;
To użycie klasy
Trace
musi zawierać odwołanie do klasy, którą kojarzy z strumieniem plików. To wymaganie oznacza, że kalkulator działa lepiej jako obiekt, dlatego dodaj konstruktor na początku klasyCalculator
w CalculatorLibrary.cs.Usuń także słowo kluczowe
static
, aby przekształcić metodę statycznąDoOperation
w metodę składową.// 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) {
Dodaj dane wyjściowe dziennika do każdego obliczenia.
DoOperation
powinien teraz wyglądać podobnie do następującego kodu:// 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; }
Powrót do Program.cs, czerwone faliste podkreślenie teraz wskazuje na wywołanie statyczne. Aby rozwiązać ten problem, utwórz zmienną
calculator
, dodając następujący wiersz kodu tuż przed pętląwhile (!endApp)
:// Program.cs Calculator calculator = new Calculator();
Zmodyfikuj również lokację wywołania
DoOperation
, aby odwoływać się do obiektu o nazwiecalculator
małymi literami. Kod jest teraz wywołaniem elementu członkowskiego, a nie wywołaniem metody statycznej.// Program.cs result = calculator.DoOperation(cleanNum1, cleanNum2, op);
Ponownie uruchom aplikację. Po zakończeniu kliknij prawym przyciskiem myszy węzeł projektu Kalkulator i wybierz "Otwórz folder w Eksploratorze plików" .
W Eksploratorze plików przejdź do folderu wyjściowego w obszarze bin/Debug/i otwórz plik calculator.log. Dane wyjściowe powinny wyglądać mniej więcej tak:
Starting Calculator Log Started 7/9/2020 1:58:19 PM 1 + 2 = 3 3 * 3 = 9
W tym momencie CalculatorLibrary.cs powinny wyglądać podobnie do tego kodu:
// 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 powinien wyglądać podobnie do następującego kodu:
// 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;
}
}
}
Dodaj pakiet NuGet: zapisz w pliku JSON
Aby wykonać operacje wyjściowe w formacie JSON, popularnym i przenośnym formacie do przechowywania danych obiektu, możesz odwołać się do pakietu NuGet Newtonsoft.Json. Pakiety NuGet to podstawowa metoda dystrybucji bibliotek klas platformy .NET.
W eksploratorze rozwiązań kliknij prawym przyciskiem myszy węzeł zależności dla projektu CalculatorLibrary, a następnie wybierz Zarządzaj pakietami NuGet.
Zostanie otwarty Menedżer pakietów NuGet.
Wyszukaj i wybierz pakiet Newtonsoft.Json, a następnie wybierz pozycję Zainstaluj.
Program Visual Studio pobiera pakiet i dodaje go do projektu. Nowy wpis zostanie wyświetlony w węźle Odwołania w eksploratorze rozwiązań .
Jeśli zostanie wyświetlony monit o zaakceptowanie zmian, wybierz pozycję OK.
Program Visual Studio pobiera pakiet i dodaje go do projektu. Nowy wpis pojawia się w węźle Packages w eksploratorze rozwiązań .
Dodaj dyrektywę
using
dlaNewtonsoft.Json
na początku CalculatorLibrary.cs.// CalculatorLibrary.cs using Newtonsoft.Json;
Utwórz obiekt członkowski
JsonWriter
i zastąp konstruktorCalculator
następującym kodem:// 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(); }
Zmodyfikuj metodę
DoOperation
, aby dodać kodwriter
JSON:// 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; }
Dodaj metodę, aby zakończyć składnię JSON po zakończeniu wprowadzania danych operacji przez użytkownika.
// CalculatorLibrary.cs public void Finish() { writer.WriteEndArray(); writer.WriteEndObject(); writer.Close(); }
Na końcu Program.cs, przed
return;
, dodaj wywołanie funkcjiFinish
:// Program.cs // Add call to close the JSON writer before return calculator.Finish(); return; }
Skompiluj i uruchom aplikację, a po zakończeniu wprowadzania kilku operacji zamknij aplikację, wprowadzając polecenie n.
Otwórz plik calculatorlog.json w Eksploratorze plików. Powinna zostać wyświetlona zawartość podobna do następującej:
{ "Operations": [ { "Operand1": 2.0, "Operand2": 3.0, "Operation": "Add", "Result": 5.0 }, { "Operand1": 3.0, "Operand2": 4.0, "Operation": "Multiply", "Result": 12.0 } ] }
Debugowanie: ustaw punkt przerwania i traf w niego
Debuger programu Visual Studio to zaawansowane narzędzie. Debuger może przejść przez kod, aby znaleźć dokładny punkt, w którym wystąpił błąd programowania. Następnie możesz zrozumieć, jakie poprawki należy wprowadzić, i wprowadzić tymczasowe zmiany, aby móc kontynuować uruchamianie aplikacji.
W Program.cskliknij w margines po lewej stronie poniższego wiersza kodu. Możesz również kliknąć linię i wybrać pozycję F9lub kliknąć linię prawym przyciskiem myszy i wybrać punkt przerwania>Wstaw punkt przerwania.
// Program.cs result = calculator.DoOperation(cleanNum1, cleanNum2, op);
Zostanie wyświetlona czerwona kropka wskazująca punkt przerwania. Możesz użyć punktów przerwania, aby wstrzymać aplikację i sprawdzić kod. Punkt przerwania można ustawić na dowolnym wykonywalnym wierszu kodu.
Skompiluj i uruchom aplikację. Wprowadź następujące wartości dla obliczenia:
- Dla pierwszej liczby wprowadź 8.
- W przypadku drugiej liczby wprowadź 0.
- Dla operatora bawmy się dobrze. Wprowadź d.
Aplikacja zawiesza się w miejscu utworzenia punktu przerwania, który jest wskazywany przez żółty wskaźnik po lewej stronie i wyróżniony kod. Wyróżniony kod nie został jeszcze wykonany.
punktu przerwania
Teraz po wstrzymaniu aplikacji możesz sprawdzić stan aplikacji.
Debugowanie: Wyświetlanie zmiennych
W wyróżnionym kodzie najedź kursorem na zmienne, takie jak
cleanNum1
iop
. Bieżące wartości tych zmiennych,8
id
, są wyświetlane we wskazówkach danych.Podczas debugowania sprawdź, czy zmienne przechowują oczekiwane wartości, często ma kluczowe znaczenie dla rozwiązywania problemów.
W dolnym okienku przyjrzyj się oknie Ustawienia lokalne. Jeśli jest zamknięte, wybierz Debug>Windows>Lokalne, aby je otworzyć.
W oknie Locals jest wyświetlana każda zmienna, która jest obecnie w zakresie, wraz z jego wartością i typem.
Spójrz na okno Autos.
Okno Autos jest podobne do okna Locals, ale pokazuje zmienne bezpośrednio poprzedzające i postępując zgodnie z bieżącym wierszem kodu, w którym aplikacja jest wstrzymana.
Notatka
Jeśli nie widzisz okna Autos, wybierz pozycję Debugowanie>Okna>Autos, aby je otworzyć.
Następnie wykonaj kod w jednej instrukcji debugera, która jest nazywana krokami.
Debugowanie: przechodzenie krok po kroku przez kod
Naciśnij F11lub wybierz Debug>Wejdź do.
Za pomocą polecenia Step Into, aplikacja wykonuje bieżącą instrukcję i przechodzi do następnej instrukcji wykonywalnej, zwykle w następnej linii kodu. Żółty wskaźnik po lewej stronie zawsze wskazuje bieżącą instrukcję.
polecenia
Właśnie wszedłeś do metody
DoOperation
w klasieCalculator
.Aby uzyskać hierarchiczny obraz przepływu programu, zajrzyj do okna Stosu Wywołań . Jeśli jest zamknięte, wybierz Debug>Windows>stos wywołań, aby go otworzyć.
stos wywołań
Ten widok przedstawia bieżącą metodę
Calculator.DoOperation
wskazywaną przez żółty wskaźnik. Drugi wiersz przedstawia funkcję, która nazwała metodę , z metodyMain
w Program.cs.W oknie stos wywołań przedstawiono kolejność wywoływania metod i funkcji. To okno zapewnia również dostęp do wielu funkcji debugera, takich jak Przejdź do kodu źródłowego, z menu skrótów.
Naciśnij F10lub wybierz Debug>Step Over, kilka razy, aż aplikacja zatrzyma się na instrukcji
switch
.// CalculatorLibrary.cs switch (op) {
Polecenie Step Over jest podobne do polecenia Step Into, z tą różnicą, że jeśli bieżąca instrukcja wywołuje funkcję, debuger uruchamia kod w funkcji i nie zawiesza wykonywania, dopóki funkcja nie powróci. Krok przez jest szybszy niż Krok do wewnątrz, jeśli nie interesuje Cię określona funkcja.
Naciśnij F10 jeszcze raz, aby aplikacja wstrzymała się w następującym wierszu kodu.
// CalculatorLibrary.cs if (num2 != 0) {
Ten kod sprawdza przypadek dzielenia przez zero. Jeśli aplikacja będzie nadal działać, wyrzuca ogólny wyjątek (błąd), ale możesz spróbować wykonać inne czynności, na przykład wyświetlenie rzeczywistej zwróconej wartości w konsoli. Jedną z opcji jest użycie funkcji debugera o nazwie edit-and-continue, aby wprowadzić zmiany w kodzie, a następnie kontynuować debugowanie. Istnieje jednak inna sztuczka, aby tymczasowo zmodyfikować przepływ wykonywania.
Debugowanie: testowanie tymczasowej zmiany
Wybierz żółty wskaźnik, który jest obecnie wstrzymany na instrukcji
if (num2 != 0)
, a następnie przeciągnij go do następującej instrukcji:// CalculatorLibrary.cs result = num1 / num2;
Przeciągnięcie wskaźnika powoduje, że aplikacja całkowicie pomija instrukcję
if
, żeby zobaczyć, co się stanie po podzieleniu przez zero.Naciśnij F10, aby wykonać wiersz kodu.
Jeśli umieścisz wskaźnik myszy na zmiennej
result
, zostanie wyświetlona wartość Infinity. W języku C# nieskończoność jest wynikiem dzielenia przez zero.Naciśnij F5lub wybierz pozycję Debugowanie>Kontynuuj debugowanie.
Symbol nieskończoności pojawia się w konsoli w wyniku operacji matematycznej.
Zamknij aplikację prawidłowo, wprowadzając polecenie n.
Kod kompletny
Oto kompletny kod pliku CalculatorLibrary.cs po wykonaniu wszystkich kroków:
// 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();
}
}
}
Oto kod dla 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;
}
}
}
Oto kompletny kod pliku CalculatorLibrary.cs po wykonaniu wszystkich kroków:
// 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();
}
}
}
Oto kod dla 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;
}
}
}
Następne kroki
Gratulujemy ukończenia tego samouczka! Aby dowiedzieć się więcej, kontynuuj pracę z następującą zawartością:
- kontynuuj korzystanie z kolejnych samouczków języka C#
- Szybki start: tworzenie aplikacji internetowej ASP.NET Core
- Dowiedz się, jak debugować kod języka C# w programie Visual Studio
- Przewodnik po tworzeniu i uruchamianiu testów jednostkowych
- Uruchom program w języku C#
- dowiedz się więcej o funkcji IntelliSense języka C#
- Kontynuuj przegląd środowiska IDE Visual Studio
- rejestrowanie i śledzenie