Tutorial: Extensión de la aplicación de consola de C# y depuración en Visual Studio (parte 2 de 2)
En la parte 2 de esta serie de tutoriales, profundizará un poco más en las características de compilación y depuración de Visual Studio que necesita para el desarrollo diario. Estas características incluyen administrar varios proyectos, depurar y hacer referencia a paquetes de terceros. Ejecute la aplicación de consola de C# que creó en parte 1 de este tutorialy explore algunas características del entorno de desarrollo integrado (IDE) de Visual Studio. Este tutorial es la parte 2 de una serie de tutoriales de dos partes.
En este tutorial, completará las siguientes tareas:
- Agregue un segundo proyecto.
- Hacer referencia a bibliotecas y agregar paquetes.
- Depure el código que ha creado.
- Inspeccionar el código completo.
Prerrequisitos
Para trabajar con este artículo, puede usar cualquiera de estas aplicaciones de calculadora:
- La aplicación de consola de calculadora de la parte 1 de este tutorial.
- La aplicación calculadora de C# en el repositorio vs-tutorial-samples. Para empezar, abrir la aplicación desde el repositorio.
Agregar otro proyecto
El código real implica proyectos que trabajan juntos en una solución. Puede agregar un proyecto de biblioteca de clases a la aplicación de calculadora que proporciona algunas funciones de calculadora.
En Visual Studio, se usa el comando de menú Archivo>Agregar>Nuevo proyecto para agregar un nuevo proyecto. También puede hacer clic con el botón derecho en la solución en Explorador de soluciones para agregar un proyecto desde el menú contextual.
En el Explorador de soluciones, haga clic con el botón derecho en el nodo de la solución y elija Agregar>Nuevo proyecto.
En la ventana Agregar un nuevo proyecto, escriba biblioteca de clases en el cuadro de búsqueda. Elija la plantilla de proyecto Biblioteca de clases de C# y seleccione Siguiente.
En la pantalla Configura tu nuevo proyecto, escriba el nombre del proyecto CalculatorLibraryy seleccione Siguiente.
Elija .NET 3.1 cuando se le pregunte. Visual Studio crea el nuevo proyecto y lo agrega a la solución.
Cambie el nombre del archivo Class1.cs a CalculatorLibrary.cs. Para cambiar el nombre del archivo, puede hacer clic con el botón derecho en el nombre en el Explorador de Soluciones y elegir Cambiar nombre, seleccionar el nombre y presionar F2, o seleccionar el nombre y volver a hacer clic para escribir.
Un mensaje puede preguntar si desea cambiar el nombre de las referencias a
Class1
en el archivo. No importa cómo responda, ya que reemplazará el código en un paso futuro.Ahora agregue una referencia de proyecto para que el primer proyecto pueda usar las API que expone la nueva biblioteca de clases. Haga clic con el botón derecho en el nodo Dependencias del proyecto Calculator y seleccione Agregar referencia de proyecto.
Aparecerá el cuadro de diálogo Administrador de referencias. En este cuadro de diálogo, puede agregar referencias a otros proyectos, ensamblados y archivos DLL COM que tus proyectos necesitan.
En el cuadro de diálogo Administrador de referencias, active la casilla correspondiente al proyecto CalculatorLibrary y seleccione Aceptar.
La referencia del proyecto aparece en un nodo Proyectos en el Explorador de soluciones.
En Program.cs, seleccione la clase
Calculator
y todo su código y presione Ctrl+X para cortarlo. A continuación, en CalculatorLibrary.cs, pegue el código dentro del espacio de nombresCalculatorLibrary
.Agregue también
public
antes de la clase Calculator para exponerla fuera de la biblioteca.CalculatorLibrary.cs ahora debería parecerse al código siguiente:
// 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 también tiene una referencia, pero un error indica que la llamada
Calculator.DoOperation
no se resuelve. El error se debe a queCalculatorLibrary
está en un espacio de nombres diferente. Para obtener una referencia completamente calificada, podría agregar el espacio de nombresCalculatorLibrary
a la llamadaCalculator.DoOperation
en Program.cs:// Program.cs result = CalculatorLibrary.Calculator.DoOperation(cleanNum1, cleanNum2, op);
O bien, podría intentar agregar una directiva
using
al principio del archivo Program.cs:// Program.cs using CalculatorLibrary;
Agregar la directiva
using
debería permitirle quitar el espacio de nombresCalculatorLibrary
del sitio de llamada, pero ahora hay una ambigüedad. ¿EsCalculator
la clase deCalculatorLibrary
, o esCalculator
el espacio de nombres?Para resolver la ambigüedad, cambie el nombre del espacio de nombres de
Calculator
aCalculatorProgram
en Program.cs.// Program.cs namespace CalculatorProgram
En el Explorador de soluciones, haga clic con el botón derecho en el nodo de la solución y elija Agregar>Nuevo proyecto.
En la ventana Agregar un nuevo proyecto, escriba biblioteca de clases en el cuadro de búsqueda. Elija la plantilla de proyecto Biblioteca de clases de C# y seleccione Siguiente.
En la pantalla Configurar el nuevo proyecto, escriba el nombre del proyecto CalculatorLibrary y, después, seleccione Siguiente.
En la pantalla Información adicional, está seleccionado .NET 8.0. Seleccione Crear.
Visual Studio crea el nuevo proyecto y lo agrega a la solución.
Cambie el nombre del archivo Class1.cs a CalculatorLibrary.cs. Para cambiar el nombre del archivo, puede hacer clic con el botón derecho en el nombre de Explorador de Soluciones y elegir Cambiar nombre, seleccionar el nombre y presionar F2, o seleccionar el nombre y volver a seleccionarlo para escribir.
Un mensaje puede preguntar si desea cambiar el nombre de todas las referencias a
Class1
en el archivo. No importa cómo responda, ya que reemplazará el código en un paso futuro.Ahora agregue una referencia de proyecto para que el primer proyecto pueda usar las API que expone la nueva biblioteca de clases. Haga clic con el botón derecho en el nodo Dependencias del proyecto Calculator y seleccione Agregar referencia de proyecto.
Aparecerá el cuadro de diálogo Administrador de referencias. En este cuadro de diálogo, puede agregar referencias a otros proyectos, ensamblados y archivos DLL COM que tus proyectos necesitan.
En el cuadro de diálogo Administrador de referencias, active la casilla correspondiente al proyecto CalculatorLibrary y seleccione Aceptar.
La referencia del proyecto aparece en un nodo Proyectos en el Explorador de soluciones.
En Program.cs, seleccione la clase
Calculator
y todo su código y presione Ctrl+X para cortarlo. Después, en CalculatorLibrary.cs, pegue el código en el espacio de nombresCalculatorLibrary
.Agregue también
public
antes de la clase Calculator para exponerla fuera de la biblioteca.CalculatorLibrary.cs ahora debería parecerse al código siguiente:
// 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 también tiene una referencia, pero un error indica que la llamada
Calculator.DoOperation
no se resuelve. El error se debe a queCalculatorLibrary
está en un espacio de nombres diferente. Para obtener una referencia completamente calificada, podría agregar el espacio de nombresCalculatorLibrary
a la llamadaCalculator.DoOperation
en Program.cs:// Program.cs result = CalculatorLibrary.Calculator.DoOperation(cleanNum1, cleanNum2, op);
O bien, podría intentar agregar una directiva
using
al principio del archivo Program.cs:// Program.cs using CalculatorLibrary;
Agregar la directiva
using
debe permitirle quitar el espacio de nombresCalculatorLibrary
del sitio de llamada.Si el código de
Program.cs
está en el espacio de nombresCalculator
, cambie el nombre del espacio de nombres deCalculator
aCalculatorProgram
para quitar la ambigüedad entre el nombre de clase y el nombre del espacio de nombres.
Referencia a bibliotecas de .NET: escritura en un registro
Puede usar la clase Trace .NET para agregar un registro de todas las operaciones y escribirlo en un archivo de texto. La clase Trace
también es útil para las técnicas básicas de impresión de la depuración. La clase Trace
está en System.Diagnostics
y usa clases System.IO
como StreamWriter
.
Empiece agregando las directivas
using
en la parte superior de CalculatorLibrary.cs:// CalculatorLibrary.cs using System.IO; using System.Diagnostics;
Este uso de la clase
Trace
debe mantener una referencia para la clase, que asocia a una secuencia de archivos. Ese requisito significa que la calculadora funciona mejor como un objeto, por lo que agregue un constructor al principio de la claseCalculator
en CalculatorLibrary.cs.Quite también la palabra clave
static
para cambiar el método estáticoDoOperation
a un método miembro.// 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) {
Agregue la salida del registro a cada cálculo.
DoOperation
ahora debería tener un aspecto similar al código siguiente:// 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; }
En Program.cs, un subrayado ondulado rojo marca ahora la llamada estática. Para corregir el error, cree una variable
calculator
agregando la siguiente línea de código justo antes del buclewhile (!endApp)
:// Program.cs Calculator calculator = new Calculator();
Modifique también el sitio de llamada de
DoOperation
para hacer referencia al objeto denominadocalculator
en minúsculas. El código es ahora una invocación de miembro, en lugar de una llamada a un método estático.// Program.cs result = calculator.DoOperation(cleanNum1, cleanNum2, op);
Vuelva a ejecutar la aplicación. Cuando haya terminado, haga clic con el botón derecho en el nodo de proyecto Calculator y elija Abrir la carpeta en el Explorador de archivos.
En el Explorador de archivos, vaya a la carpeta de salida en bin/Debug/net8.0 (o cualquier versión de .NET que use) y abra el archivo calculator.log. La salida debe tener un aspecto similar al siguiente:
Starting Calculator Log Started 7/9/2020 1:58:19 PM 1 + 2 = 3 3 * 3 = 9
En este momento, CalculatorLibrary.cs deben parecerse a este código:
// 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 debe tener un aspecto similar al código siguiente:
// 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;
}
}
}
Puede usar la clase Trace .NET para agregar un registro de todas las operaciones y escribirlo en un archivo de texto. La clase Trace
también es útil para las técnicas básicas de impresión de la depuración. La clase Trace
está en System.Diagnostics
y usa clases System.IO
como StreamWriter
.
Empiece agregando las directivas
using
en la parte superior de CalculatorLibrary.cs:// CalculatorLibrary.cs using System.Diagnostics;
Este uso de la clase
Trace
debe mantener una referencia para la clase, ya que la asocia con un flujo de archivos. Ese requisito significa que la calculadora funciona mejor como un objeto, por lo que agregue un constructor al principio de la claseCalculator
en CalculatorLibrary.cs.Quite también la palabra clave
static
para cambiar el método estáticoDoOperation
a un método miembro.// 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) {
Agregue la salida del registro a cada cálculo.
DoOperation
ahora debería tener un aspecto similar al código siguiente:// 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; }
En Program.cs, un subrayado ondulado rojo marca ahora la llamada estática. Para corregir el error, cree una variable
calculator
agregando la siguiente línea de código justo antes del buclewhile (!endApp)
:// Program.cs Calculator calculator = new Calculator();
Modifique también el sitio de llamada de
DoOperation
para hacer referencia al objeto denominadocalculator
en minúsculas. El código es ahora una invocación de miembro, en lugar de una llamada a un método estático.// Program.cs result = calculator.DoOperation(cleanNum1, cleanNum2, op);
Vuelva a ejecutar la aplicación. Cuando haya terminado, haga clic con el botón derecho en el nodo de proyecto Calculator y elija Abrir la carpeta en el Explorador de archivos.
En el Explorador de archivos, vaya a la carpeta de salida en bin/Debug/y abra el archivo calculator.log. La salida debe tener un aspecto similar al siguiente:
Starting Calculator Log Started 7/9/2020 1:58:19 PM 1 + 2 = 3 3 * 3 = 9
En este momento, CalculatorLibrary.cs deben parecerse a este código:
// 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 debe tener un aspecto similar al código siguiente:
// 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;
}
}
}
Agregar un paquete NuGet: escribir en un archivo JSON
Para generar operaciones en JSON, un formato popular y portátil para almacenar datos de objeto, puede hacer referencia al paquete NuGet Newtonsoft.Json. Los paquetes NuGet son el método de distribución principal para las bibliotecas de clases de .NET.
En Explorador de soluciones, haga clic con el botón derecho en el nodo Dependencias del proyecto CalculatorLibrary y elija Administrar paquetes NuGet.
Se abre el Administrador de paquetes NuGet.
Busque y seleccione el paquete Newtonsoft.Json, y luego seleccione Instalar.
Visual Studio descarga el paquete y lo agrega al proyecto. Aparece una nueva entrada en el nodo Referencias de Explorador de soluciones.
Si se le pide que acepte cambios, seleccione Aceptar.
Visual Studio descarga el paquete y lo agrega al proyecto. Aparece una nueva entrada en el nodo Paquetes del Explorador de soluciones.
Agregue una directiva
using
paraNewtonsoft.Json
al principio de CalculatorLibrary.cs.// CalculatorLibrary.cs using Newtonsoft.Json;
Cree el objeto miembro
JsonWriter
y reemplace el constructorCalculator
por el código siguiente:// 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(); }
Modifique el método
DoOperation
para agregar el código dewriter
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; }
Agregue un método para finalizar la sintaxis JSON una vez que el usuario haya terminado de escribir los datos de la operación.
// CalculatorLibrary.cs public void Finish() { writer.WriteEndArray(); writer.WriteEndObject(); writer.Close(); }
Al final de Program.cs, antes de
return;
, agregue una llamada aFinish
:// Program.cs // Add call to close the JSON writer before return calculator.Finish(); return; }
Compile y ejecute la aplicación y, después de que haya terminado de escribir algunas operaciones, cierre la aplicación escribiendo el comando n.
Abra el archivo calculatorlog.json en el Explorador de archivos. Debería ver algo parecido al siguiente contenido:
{ "Operations": [ { "Operand1": 2.0, "Operand2": 3.0, "Operation": "Add", "Result": 5.0 }, { "Operand1": 3.0, "Operand2": 4.0, "Operation": "Multiply", "Result": 12.0 } ] }
Depuración: establecimiento y uso de los puntos de interrupción
El depurador de Visual Studio es una herramienta eficaz. El depurador puede recorrer el código para encontrar el punto exacto en el que hay un error de programación. A continuación, puede comprender qué correcciones necesita realizar y realizar cambios temporales para que pueda seguir ejecutando la aplicación.
En Program.cs, haga clic en el margen de la izquierda de la siguiente línea de código. También puede hacer clic en la línea y seleccionar F9, o haga clic con el botón derecho en la línea y seleccione Punto de interrupción>Insertar punto de interrupción.
// Program.cs result = calculator.DoOperation(cleanNum1, cleanNum2, op);
El punto rojo que aparece indica un punto de interrupción. Puedes usar puntos de interrupción para pausar la aplicación e inspeccionar el código. Puede establecer un punto de interrupción en cualquier línea de código ejecutable.
Compile y ejecute la aplicación. Escriba los valores siguientes para el cálculo:
- Para el primer número, escriba 8.
- En el segundo número, escriba 0.
- Para el operador, divirtámonos un poco: Escriba d.
La aplicación se suspende donde creó el punto de interrupción, que se indica mediante el puntero amarillo de la izquierda y el código resaltado. El código resaltado aún no se ha ejecutado.
Ahora, con la aplicación suspendida, puede inspeccionar el estado de la aplicación.
Depuración: ver variables
En el código resaltado, mantenga el puntero sobre variables como
cleanNum1
yop
. Los valores actuales de estas variables,8
yd
respectivamente, aparecen en Información sobre datos.Al depurar, comprobar si las variables contienen los valores esperados suele ser fundamental para corregir problemas.
En el panel inferior, examine la ventana Variables locales. Si está cerrada, seleccione Depurar>Ventanas>Variables locales para abrirla.
La ventana Variables locales muestra cada variable que está actualmente en el ámbito, junto con su valor y tipo.
Fíjese en la ventana Automático.
La ventana Automático es similar a la ventana Variables locales, pero muestra las variables inmediatamente anteriores y posteriores a la línea de código actual en la que está pausada la aplicación.
Nota
Si no ve la ventana Automático, seleccione Depurar>Windows>Automático para abrirla.
A continuación, ejecute el código en el depurador instrucción por instrucción, lo que se denomina ejecución paso a paso.
Depuración: examinar el código
Presione F11 o seleccione Depurar>Depurar paso a paso por instrucciones.
Con el comando Step Into, la aplicación ejecuta la instrucción actual y avanza a la siguiente instrucción ejecutable, normalmente la siguiente línea de código. El puntero amarillo de la izquierda siempre indica la instrucción actual.
Acaba de depurar paso a paso por instrucciones el método
DoOperation
de la claseCalculator
.Para obtener una visión jerárquica del flujo del programa, examine la ventana Pila de llamadas. Si está cerrada, seleccione Depurar>Ventanas>Pila de llamadas para abrirla.
Esta vista muestra el método
Calculator.DoOperation
actual, indicado por el puntero amarillo. La segunda fila muestra la función que llamó al método, desde el métodoMain
en Program.cs.En la ventana Pila de llamadas se muestra el orden en el que se llama a los métodos y las funciones. Esta ventana también proporciona acceso a muchas características del depurador, como Ir al código fuente, desde su menú contextual.
Presione F10 (o seleccione Depurar>Depurar paso a paso por procedimientos) varias veces hasta que la aplicación se pause en la instrucción
switch
.// CalculatorLibrary.cs switch (op) {
El comando Step Over es similar al comando Step Into, excepto que si la instrucción actual llama a una función, el depurador ejecuta el código de la función y no suspende la ejecución hasta que la función devuelve. Depurar paso a paso por procedimientos es más rápido que Depurar paso a paso por instrucciones si no está interesado en una función determinada.
Presione F10 una vez más para que la aplicación se detenga en la siguiente línea de código.
// CalculatorLibrary.cs if (num2 != 0) {
Este código comprueba si hay un caso de división por cero. Si la aplicación continúa, produce una excepción general (un error), pero es posible que quiera probar otra cosa, como ver el valor devuelto real en la consola. Una opción es usar una característica del depurador llamada editar y continuar para realizar cambios en el código y, a continuación, continuar con la depuración. Sin embargo, hay un truco diferente para modificar temporalmente el flujo de ejecución.
Depuración: probar un cambio temporal
Seleccione el puntero amarillo, actualmente en pausa en la instrucción
if (num2 != 0)
, y arrástrelo a la siguiente instrucción:// CalculatorLibrary.cs result = num1 / num2;
Arrastrar el puntero aquí hace que la aplicación omita completamente la instrucción
if
, por lo que puede ver lo que sucede cuando se divide por cero.Presione F10 para ejecutar la línea de código.
Si coloca el cursor sobre la variable
result
, muestra un valor de Infinito. En C#, Infinity es el resultado cuando se divide por cero.Presione F5, o seleccione Depurar>Continuar depurando.
El símbolo infinito aparece en la consola como resultado de la operación matemática.
Cierre correctamente la aplicación escribiendo el comando n.
Código completado
Este es el código completo del archivo CalculatorLibrary.cs, después de completar todos los pasos:
// 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();
}
}
}
Y este es el código de 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;
}
}
}
Este es el código completo del archivo CalculatorLibrary.cs, después de completar todos los pasos:
// 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();
}
}
}
Y este es el código de 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;
}
}
}
Pasos siguientes
Enhorabuena por completar este tutorial. Para más información, continúe con el siguiente contenido:
- continuar con más tutoriales de C#
- Inicio rápido de : Creación de una aplicación web ASP.NET Core
- Aprender a depurar código de C# en Visual Studio
- Tutorial sobre cómo crear y ejecutar pruebas unitarias
- Ejecutar un programa de C#
- Información sobre IntelliSense para C#
- Continuar con la introducción al IDE de Visual Studio
- Registro y seguimiento