Menu

Hola mundo en C#: Main, Console.WriteLine y ReadLine

Tu primer programa en C# línea a línea: el método Main, Console.WriteLine y Write, leer la entrada con Console.ReadLine, los comentarios, crear y ejecutar un proyecto con la CLI de dotnet, y las instrucciones de nivel superior.

Esta página incluye editores ejecutables: edita, ejecuta y ve el resultado al instante.

El primer programa clásico imprime una línea de texto. En C# es así:

Salida:

Hello, World!

Línea a línea

  • using System; te permite escribir Console en lugar del nombre completo System.Console. Console es una clase del namespace System (consulta namespaces y using).
  • class Program declara una clase. Todo el código C# vive dentro de un tipo; el nombre Program es una convención, no un requisito.
  • static void Main() es el punto de entrada. Cuando el programa empieza, el runtime busca un método static llamado Main y lo llama. static significa que pertenece a la propia clase, así que no hace falta crear antes ningún objeto. void significa que no devuelve nada.
  • Console.WriteLine("Hello, World!"); llama al método WriteLine con un argumento string. Cada sentencia termina con punto y coma.
  • Las llaves { } marcan el cuerpo de la clase y el del método.

C# distingue mayúsculas y minúsculas. console.writeline y main son nombres distintos de Console.WriteLine y Main, y ninguno de los dos existe.

Console.WriteLine frente a Console.Write

WriteLine añade un salto de línea después del texto. Write no, así que la siguiente salida continúa en la misma línea. Los dos aceptan cualquier tipo, no solo strings: los números, los booleanos y los objetos se convierten con su método ToString().

Salida:

Loading.. done
42
True

Item: coffee
coffee costs 3.20
coffee costs 3.20

Fíjate en que true se imprime como True: eso es lo que devuelve bool.ToString(). La forma $"...", llamada interpolación de strings, es la que más usarás; consulta interpolación de strings para los códigos de formato como :F2.

Leer la entrada con Console.ReadLine

Console.ReadLine() espera a que el usuario escriba una línea y pulse Enter, y después devuelve esa línea como string sin el salto de línea. Al final de la entrada (por ejemplo, cuando la entrada se redirige desde un archivo que se ha terminado) devuelve null.

Salida:

What is your name? How old are you? 
Hi Maya, next year you will be 28.

Cuando lo ejecutas en una terminal, el texto que escribes aparece después de cada pregunta. La salida de arriba no contiene texto escrito porque la entrada se redirigió (se pasó por una tubería) en lugar de escribirse, así que solo aparece lo que escribe el propio programa.

ReadLine siempre devuelve texto. Para usar el valor como número tienes que convertirlo. int.Parse(text) lanza una FormatException cuando el texto no es un número; int.TryParse devuelve false en su lugar, y por eso es la opción correcta para la entrada del usuario. Los detalles están en conversión de tipos.

Dos métodos relacionados: Console.Read() devuelve el siguiente carácter como código int, y Console.ReadKey() lee una sola pulsación de tecla sin esperar a Enter (solo funciona en una terminal interactiva).

Las otras formas del método Main

Main puede recibir los argumentos de la línea de comandos y puede devolver un código de salida. Todos estos son puntos de entrada válidos:

static void Main()
static void Main(string[] args)
static int Main()
static int Main(string[] args)
static async Task Main()             // C# 7.1 and later
static async Task<int> Main(string[] args)  // C# 7.1 and later

Un int devuelto se convierte en el código de salida del proceso, que los scripts y los sistemas de CI leen para decidir si el programa funcionó (0 significa éxito por convención).

Salida:

Got 0 argument(s)

Ejecútalo con dotnet run -- apples pears y args contendrá "apples" y "pears". El -- separa los argumentos de tu programa de los argumentos de la herramienta dotnet.

Comentarios

C# tiene tres tipos de comentarios. El compilador los ignora todos.

// A single-line comment runs to the end of the line.

/* A block comment
   can span several lines. */

/// <summary>
/// An XML documentation comment. Editors show it as the tooltip for the method.
/// </summary>
static decimal ApplyDiscount(decimal price) => price * 0.9m;

Usa // para las notas dentro del código. Los comentarios /// van sobre los tipos y los miembros públicos; el IDE los muestra cuando pasas el ratón sobre una llamada, y el compilador puede exportarlos a un archivo XML para las herramientas de documentación.

Crear y ejecutar un proyecto con dotnet

En tu propia máquina, instala el SDK de .NET desde dotnet.microsoft.com y después:

dotnet new console -o HelloApp
cd HelloApp
dotnet run
Hello, World!

dotnet new console crea dos archivos: HelloApp.csproj (el archivo de proyecto: framework de destino, configuración, referencias a paquetes) y Program.cs. dotnet run compila el proyecto y lo ejecuta. dotnet build compila sin ejecutar y escribe el resultado en bin/Debug/net8.0/ (el nombre de la carpeta sigue a tu framework de destino).

Instrucciones de nivel superior (C# 9 y posteriores)

Abre el Program.cs generado y encontrarás esto, y nada más:

// See https://aka.ms/new-console-template for more information
Console.WriteLine("Hello, World!");

Es un programa con instrucciones de nivel superior, una característica de C# 9. El compilador genera la clase Program y el método Main alrededor de tus sentencias. También falta using System; porque los proyectos de .NET 6 y posteriores activan los usings implícitos: los namespaces habituales como System, System.IO, System.Linq y System.Collections.Generic se importan para todo el proyecto.

Los programas de nivel superior pueden seguir leyendo args, usar await y hacer return de un código de salida:

// C# 9 and later: the whole Program.cs
Console.Write("Name: ");
string? name = Console.ReadLine();
Console.WriteLine($"Hello, {name}! You passed {args.Length} arguments.");
return 0;

Solo un archivo por proyecto puede contener instrucciones de nivel superior, y los tipos (clases, records) deben ir después de ellas. La anotación string? es un tipo de referencia nullable (C# 8), y está ahí porque ReadLine puede devolver null. La forma explícita con class Program que usan los ejemplos de esta página es equivalente y es la que verás en código antiguo y en la mayoría de los scripts de Unity, así que conviene saber leer las dos. Pasa --use-program-main a dotnet new console si prefieres la forma explícita en proyectos nuevos.

Los primeros errores que verás

  • CS1002: ; expected. A una sentencia le falta el punto y coma. El error se indica al final de la línea a la que le falta.
  • CS0103: The name 'console' does not exist in the current context. Mayúsculas incorrectas, o falta using System; en un proyecto sin usings implícitos.
  • CS5001: Program does not contain a static 'Main' method suitable for an entry point. Main está mal escrito, no es static o tiene una firma no admitida.
  • CS0017: Program has more than one entry point defined. Dos clases tienen cada una un Main. Deja uno, o elige uno con la opción StartupObject del .csproj.
  • La ventana se cierra de inmediato. Cuando una aplicación de consola se abre con doble clic, la ventana se cierra cuando Main vuelve. Ejecútala desde una terminal, o añade Console.ReadKey(); al final mientras haces pruebas.

Preguntas frecuentes

¿Cómo se escribe Hola mundo en C#?

Pon Console.WriteLine("Hello, World!"); dentro de un método static void Main() de una clase, con using System; al principio. En un proyecto creado con dotnet new console en .NET 6 o posterior, el archivo entero puede ser solo esa línea, porque las instrucciones de nivel superior generan la clase y Main por ti.

¿Qué es el método Main en C#?

Main es el punto de entrada: el método al que llama el runtime cuando empieza el programa. Debe ser static, puede devolver void o int (el código de salida) y puede recibir un parámetro string[] args con los argumentos de la línea de comandos. Un programa necesita exactamente uno.

¿Qué diferencia hay entre Console.Write y Console.WriteLine?

Console.WriteLine escribe el texto seguido de un salto de línea, así que la siguiente salida empieza en una línea nueva. Console.Write escribe solo el texto, así que la siguiente salida continúa en la misma línea. Console.WriteLine() sin argumentos imprime una línea vacía.

¿Cómo leo lo que escribe el usuario en C#?

Console.ReadLine() lee una línea de texto y la devuelve como string (sin el salto de línea), o null cuando ya no hay más entrada. Para obtener un número, convierte el string: int.TryParse(Console.ReadLine(), out int n) devuelve false en lugar de fallar cuando el texto no es un número.

¿Cómo ejecuto un programa de C# desde la línea de comandos?

Instala el SDK de .NET y ejecuta dotnet new console -o HelloApp para crear un proyecto, cd HelloApp y dotnet run para compilarlo y ejecutarlo. dotnet build solo compila, y deja el resultado en bin/Debug/net8.0/ (o la versión a la que apuntes).

Coddy programming languages illustration

Aprende a programar con Coddy

COMENZAR