Descarga el código: LearnCSharp.cs
C# es un lenguaje orientado a objetos elegante y de tipado seguro que permite a los desarrolladores construir una variedad de aplicaciones seguras y robustas que se ejecutan en el Framework .NET.
// Los comentarios de una sola línea comienzan con //
/*
Los comentarios de múltiples líneas son de esta manera
*/
/// <summary>
/// Este es un comentario de documentación XML
/// </summary>
// Especifica el espacio de nombres que estará usando la aplicación
using System;
using System.Collections.Generic;
// Define un ambito para organizar el código en "paquetes"
namespace Learning
{
// Cada archivo .cs debe contener al menos una clase con el mismo nombre que el archivo
// Se permite colocar cualquier nombre, pero no deberías por cuestiones de consistencia.
public class LearnCSharp
{
// Una aplicación de consola debe tener un método main como punto de entrada
public static void Main(string[] args)
{
// Usa Console.WriteLine para imprimir líneas
Console.WriteLine("Hello World");
Console.WriteLine(
"Integer: " + 10 +
" Double: " + 3.14 +
" Boolean: " + true);
// Para imprimir sin una nueva línea, usa Console.Write
Console.Write("Hello ");
Console.Write("World");
///////////////////////////////////////////////////
// Variables y Tipos
//
// Declara una variable usando <tipo> <nombre>
///////////////////////////////////////////////////
// Sbyte - Entero de 8 bits con signo
// (-128 <= sbyte <= 127)
sbyte fooSbyte = 100;
// Byte - Entero de 8 bits sin signo
// (0 <= byte <= 255)
byte fooByte = 100;
// Short - Entero de 16 bits con signo
// (-32,768 <= short <= 32,767)
short fooShort = 10000;
// Ushort - Entero de 16 bits sin signo
// (0 <= ushort <= 65,535)
ushort fooUshort = 10000;
// Integer - Entero de 32 bits con signo
// (-2,147,483,648 <= int <= 2,147,483,647)
int fooInt = 1;
// Uinteger - Entero de 32 bits sin signo
// (0 <= uint <= 4,294,967,295)
uint fooUint = 1;
// Long - Entero de 64 bits con signo
// (-9,223,372,036,854,775,808 <= long <= 9,223,372,036,854,775,807)
long fooLong = 100000L;
// L es usado para indicar que esta variable es de tipo long o ulong
// un valor sin este sufijo es tratado como int o uint dependiendo del tamaño.
// Ulong - Entero de 64 bits sin signo
// (0 <= ulong <= 18,446,744,073,709,551,615)
ulong fooUlong = 100000L;
// Float - Precisión simple de 32 bits. IEEE 754 Coma flotante
// Precisión: 7 dígitos
float fooFloat = 234.5f;
// f es usado para indicar que el valor de esta variable es de tipo float
// de otra manera sería tratado como si fuera de tipo double.
// Double - Doble precisión de 32 bits. IEEE 754 Coma flotante
// Precisión: 15-16 dígitos
double fooDouble = 123.4;
// Bool - true & false (verdadero y falso)
bool fooBoolean = true;
bool barBoolean = false;
// Char - Un solo caracter Unicode de 16 bits
char fooChar = 'A';
// Strings
string fooString = "My string is here!";
Console.WriteLine(fooString);
// Formato de cadenas
string fooFs = string.Format("Check Check, {0} {1}, {0} {1:0.0}", 1, 2);
Console.WriteLine(fooFormattedString);
// Formato de fechas
DateTime fooDate = DateTime.Now;
Console.WriteLine(fooDate.ToString("hh:mm, dd MMM yyyy"));
// \n es un caracter de escape que comienza una nueva línea
string barString = "Printing on a new line?\nNo Problem!";
Console.WriteLine(barString);
// Puede ser escrito mejor usando el símbolo @
string bazString = @"Here's some stuff
on a new line!";
Console.WriteLine(bazString);
// Las comillas deben ser escapadas
// usa \" para escaparlas
string quotedString = "some \"quoted\" stuff";
Console.WriteLine(quotedString);
// usa "" cuando las cadenas comiencen con @
string quotedString2 = @"some MORE ""quoted"" stuff";
Console.WriteLine(quotedString2);
// Usa const o readonly para hacer las variables inmutables
// los valores const son calculados en tiempo de compilación
const int HOURS_I_WORK_PER_WEEK = 9001;
// Tipos que aceptan valores NULL (Nullable)
// cualquier tipo de dato puede ser un tipo nulo añadiendole el sufijo ?
// <tipo>? <variable> = <valor>
int? nullable = null;
Console.WriteLine("Nullable variable: " + nullable);
// Para usar valores nulos, tienes que usar la propiedad Value
// o usar conversión explícita
string? nullableString = "not null";
Console.WriteLine("Nullable value is: " + nullableString.Value + " or: " + (string) nullableString );
// ?? is una manera corta de especificar valores por defecto
// en caso de que la variable sea null
int notNullable = nullable ?? 0;
Console.WriteLine("Not nullable variable: " + notNullable);
// var - el compilador escogerá el tipo de dato más apropiado basado en el valor
var fooImplicit = true;
///////////////////////////////////////////////////
// Estructura de datos
///////////////////////////////////////////////////
Console.WriteLine("\n->Data Structures");
// Arreglos
// El tamaño del arreglo debe decidirse al momento de la declaración
// El formato para declarar un arreglo es el siguiente:
// <tipo_de_dato>[] <nombre_variable> = new <tipo_de_dato>[<tamaño>];
int[] intArray = new int[10];
string[] stringArray = new string[1];
bool[] boolArray = new bool[100];
// Otra forma de declarar e inicializar un arreglo
int[] y = { 9000, 1000, 1337 };
// Indexar arreglos - Acceder a un elemento
Console.WriteLine("intArray @ 0: " + intArray[0]);
// Los arreglos son de índice cero y son mutables.
intArray[1] = 1;
Console.WriteLine("intArray @ 1: " + intArray[1]); // => 1
// Listas
// Las listas son usadas más frecuentemente que los arreglos ya que son más flexibles
// El formato para declarar una lista es el siguiente:
// List<tipo_de_dato> <nombre_variable> = new List<tipo_de_dato>();
List<int> intList = new List<int>();
List<string> stringList = new List<string>();
// Otra forma de declarar e inicializar una lista
List<int> z = new List<int> { 9000, 1000, 1337 };
// Indexar una lista - Acceder a un elemento
// Las listas son de índice cero y son mutables.
Console.WriteLine("z @ 0: " + z[2]);
// Las listas no tienen valores por defecto;
// Un valor debe ser añadido antes de acceder al índice
intList.Add(1);
Console.WriteLine("intList @ 0: " + intList[0]);
// Otras estructuras de datos a chequear:
//
// Pilas/Colas
// Diccionarios
// Colecciones de sólo lectura
// Tuplas (.Net 4+)
///////////////////////////////////////
// Operadores
///////////////////////////////////////
Console.WriteLine("\n->Operators");
int i1 = 1, i2 = 2; // Modo corto para múltiples declaraciones
// La aritmética es sencilla
Console.WriteLine("1+2 = " + (i1 + i2)); // => 3
Console.WriteLine("2-1 = " + (i2 - i1)); // => 1
Console.WriteLine("2*1 = " + (i2 * i1)); // => 2
Console.WriteLine("1/2 = " + (i1 / i2)); // => 0 (0.5 truncated down)
// Módulo
Console.WriteLine("11%3 = " + (11 % 3)); // => 2
// Operadores de comparación
Console.WriteLine("3 == 2? " + (3 == 2)); // => false
Console.WriteLine("3 != 2? " + (3 != 2)); // => true
Console.WriteLine("3 > 2? " + (3 > 2)); // => true
Console.WriteLine("3 < 2? " + (3 < 2)); // => false
Console.WriteLine("2 <= 2? " + (2 <= 2)); // => true
Console.WriteLine("2 >= 2? " + (2 >= 2)); // => true
// Operadores a nivel de bits
/*
~ Complemento a nivel de bits
<< Desplazamiento a la izquierda con signo
>> Desplazamiento a la derecha con signo
>>> Desplazamiento a la derecha sin signo
& AND a nivel de bits
^ XOR a nivel de bits
| OR a nivel de bits
*/
// Incremento
int i = 0;
Console.WriteLine("\n->Inc/Dec-remento");
Console.WriteLine(i++); //i = 1. Posincrementación
Console.WriteLine(++i); //i = 2. Preincremento
Console.WriteLine(i--); //i = 1. Posdecremento
Console.WriteLine(--i); //i = 0. Predecremento
///////////////////////////////////////
// Estructuras de control
///////////////////////////////////////
Console.WriteLine("\n->Control Structures");
// Las condiciones if son como en lenguaje c
int j = 10;
if (j == 10)
{
Console.WriteLine("I get printed");
}
else if (j > 10)
{
Console.WriteLine("I don't");
}
else
{
Console.WriteLine("I also don't");
}
// Operador ternario
// Un simple if/else puede ser escrito de la siguiente manera;
// <condición> ? <true> : <false>
string isTrue = (true) ? "True" : "False";
Console.WriteLine("Ternary demo: " + isTrue);
// Bucle while
int fooWhile = 0;
while (fooWhile < 100)
{
//Console.WriteLine(fooWhile);
//Incrementar el contador
//Iterar 99 veces, fooWhile 0->99
fooWhile++;
}
Console.WriteLine("fooWhile Value: " + fooWhile);
// Bucle Do While
int fooDoWhile = 0;
do
{
//Console.WriteLine(fooDoWhile);
//Incrementar el contador
//Iterar 99 veces, fooDoWhile 0->99
fooDoWhile++;
} while (fooDoWhile < 100);
Console.WriteLine("fooDoWhile Value: " + fooDoWhile);
// Bucle For
int fooFor;
//Estructura del bucle for => for(<declaración_inicial>; <condición>; <incremento>)
for (fooFor = 0; fooFor < 10; fooFor++)
{
//Console.WriteLine(fooFor);
//Iterated 10 times, fooFor 0->9
}
Console.WriteLine("fooFor Value: " + fooFor);
// Switch Case
// El switch funciona con los tipos de datos byte, short, char e int
// También funciona con las enumeraciones (discutidos en in Tipos Enum),
// la clase string y algunas clases especiales que encapsulan
// tipos primitivos: Character, Byte, Short, Integer.
int month = 3;
string monthString;
switch (month)
{
case 1:
monthString = "January";
break;
case 2:
monthString = "February";
break;
case 3:
monthString = "March";
break;
default:
monthString = "Some other month";
break;
}
Console.WriteLine("Switch Case Result: " + monthString);
////////////////////////////////
// Conversión de tipos de datos
////////////////////////////////
// Convertir datos
// Convertir String a Integer
// esto generará una excepción al fallar la conversión
int.Parse("123");//retorna una versión entera de "123"
// TryParse establece la variable a un tipo por defecto
// en este caso: 0
int tryInt;
int.TryParse("123", out tryInt);
// Convertir Integer a String
// La clase Convert tiene algunos métodos para facilitar las conversiones
Convert.ToString(123);
///////////////////////////////////////
// Clases y Funciones
///////////////////////////////////////
Console.WriteLine("\n->Classes & Functions");
// (Definición de la clase Bicycle (Bicicleta))
// Usar new para instanciar una clase
Bicycle trek = new Bicycle();
// Llamar a los métodos del objeto
trek.speedUp(3); // Siempre deberías usar métodos setter y métodos getter
trek.setCadence(100);
// ToString es una convención para mostrar el valor del objeto.
Console.WriteLine("trek info: " + trek.ToString());
// Instanciar otra nueva bicicleta
Bicycle octo = new Bicycle(5, 10);
Console.WriteLine("octo info: " + octo.ToString());
// Instanciar un Penny Farthing (Biciclo)
PennyFarthing funbike = new PennyFarthing(1, 10);
Console.WriteLine("funbike info: " + funbike.ToString());
Console.Read();
} // Fin del método main
} // Fin de la clase LearnCSharp
// Puedes incluir otras clases en un archivo .cs
// Sintaxis para la declaración de clases:
// <public/private/protected> class <nombre_de_clase>{
// //campos, constructores, funciones todo adentro de la clase.
// //las funciones son llamadas métodos como en java.
// }
public class Bicycle
{
// Campos/Variables de la clase Bicycle
public int cadence; // Public: Accesible desde cualquier lado
private int _speed; // Private: Sólo es accesible desde dentro de la clase
protected int gear; // Protected: Accesible desde clases y subclases
internal int wheels; // Internal: Accesible en el ensamblado
string name; // Todo es privado por defecto: Sólo es accesible desde dentro de esta clase
// Enum es un tipo valor que consiste un una serie de constantes con nombres
public enum Brand
{
AIST,
BMC,
Electra,
Gitane
}
// Definimos este tipo dentro de la clase Bicycle, por lo tanto es un tipo anidado
// El código afuera de esta clase debería referenciar este tipo como Bicycle.Brand
public Brand brand; // Declaramos un tipo enum, podemos declarar un campo de este tipo
// Los miembros estáticos pertenecen al tipo mismo, no a un objeto en específico.
static public int bicyclesCreated = 0;
// Puedes acceder a ellos sin referenciar ningún objeto:
// Console.WriteLine("Bicycles created: " + Bicycle.bicyclesCreated);
// Los valores readonly (Sólo lectura) son establecidos en tiempo de ejecución
// sólo pueden ser asignados al momento de la declaración o dentro de un constructor
readonly bool hasCardsInSpokes = false; // privado de sólo lectura
// Los constructores son una forma de crear clases
// Este es un constructor por defecto
private Bicycle()
{
gear = 1;
cadence = 50;
_speed = 5;
name = "Bontrager";
brand = Brand.AIST;
bicyclesCreated++;
}
// Este es un constructor específico (contiene argumentos)
public Bicycle(int startCadence, int startSpeed, int startGear,
string name, bool hasCardsInSpokes, Brand brand)
{
this.gear = startGear; // La palabra reservada "this" señala el objeto actual
this.cadence = startCadence;
this._speed = startSpeed;
this.name = name; // Puede ser útil cuando hay un conflicto de nombres
this.hasCardsInSpokes = hasCardsInSpokes;
this.brand = brand;
}
// Los constructores pueden ser encadenados
public Bicycle(int startCadence, int startSpeed, Brand brand) :
this(startCadence, startSpeed, 0, "big wheels", true)
{
}
// Sintaxis para Funciones:
// <public/private/protected> <tipo_retorno> <nombre_funcion>(<args>)
// Las clases pueden implementar getters y setters para sus campos
// o pueden implementar propiedades
// Sintaxis para la declaración de métodos:
// <ámbito> <tipo_retorno> <nombre_método>(<argumentos>)
public int GetCadence()
{
return cadence;
}
// Los métodos void no requieren usar return
public void SetCadence(int newValue)
{
cadence = newValue;
}
// La palabra reservada virtual indica que este método puede ser sobrescrito
public virtual void SetGear(int newValue)
{
gear = newValue;
}
// Los parámetros de un método pueden tener valores por defecto.
// En este caso, los métodos pueden ser llamados omitiendo esos parámetros
public void SpeedUp(int increment = 1)
{
_speed += increment;
}
public void SlowDown(int decrement = 1)
{
_speed -= decrement;
}
// Propiedades y valores get/set
// Cuando los datos sólo necesitan ser accedidos, considera usar propiedades.
// Las propiedades pueden tener get, set o ambos
private bool _hasTassles; // variable privada
public bool HasTassles // acceso público
{
get { return _hasTassles; }
set { _hasTassles = value; }
}
// Las propiedades pueden ser auto implementadas
public int FrameSize
{
get;
// Puedes especificar modificadores de acceso tanto para get como para set
// esto significa que sólo dentro de la clase Bicycle se puede modificar Framesize
private set;
}
//Método para mostrar los valores de atributos de este objeto.
public override string ToString()
{
return "gear: " + gear +
" cadence: " + cadence +
" speed: " + _speed +
" name: " + name +
" cards in spokes: " + (hasCardsInSpokes ? "yes" : "no") +
"\n------------------------------\n"
;
}
// Los métodos también pueden ser estáticos. Puede ser útil para métodos de ayuda
public static bool DidWeCreateEnoughBycles()
{
// Dentro de un método esático,
// Sólo podemos hacer referencia a miembros estáticos de clases
return bicyclesCreated > 9000;
} // Si tu clase sólo necesita miembros estáticos,
// considera establecer la clase como static.
} // fin de la clase Bicycle
// PennyFarthing es una subclase de Bicycle
class PennyFarthing : Bicycle
{
// (Penny Farthings son las bicicletas con una rueda delantera enorme.
// No tienen engranajes.)
// llamar al constructor de la clase padre
public PennyFarthing(int startCadence, int startSpeed) :
base(startCadence, startSpeed, 0, "PennyFarthing", true)
{
}
public override void SetGear(int gear)
{
gear = 0;
}
public override string ToString()
{
string result = "PennyFarthing bicycle ";
result += base.ToString(); // Llamar a la versión base del método
return reuslt;
}
}
// Las interfaces sólo contienen las declaraciones
// de los miembros, sin la implementación.
interface IJumpable
{
void Jump(int meters); // todos los miembros de interfaces son implícitamente públicos
}
interface IBreakable
{
// Las interfaces pueden contener tanto propiedades como métodos, campos y eventos
bool Broken { get; }
}
// Las clases sólo heredan de alguna otra clase, pero pueden implementar
// cualquier cantidad de interfaces
class MountainBike : Bicycle, IJumpable, IBreakable
{
int damage = 0;
public void Jump(int meters)
{
damage += meters;
}
public void Broken
{
get
{
return damage > 100;
}
}
}
} // Fin del espacio de nombres
¿Tienes una sugerencia o rectificación? Abre un issue en el repositorio de GitHub, o haz un pull request tu mismo
Originalmente contribuido por Irfan Charania, y actualizado por 3 colaboradores.