Está en la página 1de 96

Origen, evolución y características

técnicas del lenguaje de programación C#

Capítulo 1: Origen y evolución del lenguaje C#

Origen del lenguaje C#

C# (pronunciado si Sharp en inglés) es un lenguaje de programación orientado a


objetos desarrollado y estandarizado por Microsoft como parte de su plataforma
.NET, que después fue aprobado como un estándar por la ECMA (ECMA-334) e
ISO (ISO/IEC 23270).

C# es uno de los lenguajes de programación diseñados para la infraestructura de


lenguaje común. Su sintaxis básica deriva de C/C++ y utiliza el modelo de objetos
de la plataforma .NET, similar al de Java, aunque incluye mejoras derivadas de
otros lenguajes.

El nombre C Sharp fue inspirado por el signo '#' que se compone de cuatro signos
'+' pegados. Aunque C# forma parte de la plataforma .NET, ésta es una API,
mientras que C# es un lenguaje de programación independiente diseñado para
generar programas sobre dicha plataforma. Ya existe un compilador implementado
que provee el marco Mono - DotGNU, el cual genera programas para distintas
plataformas como Windows Microsoft, Unix, Android, iOS, Windows Phone, Mac
OS y GNU/Linux.

Durante el desarrollo de la plataforma .NET, las bibliotecas de clases fueron


escritas originalmente usando un sistema de código gestionado llamado Simple
Managed C (SMC). En abril de 1999, Anders Hejlsberg formó un equipo con la
misión de desarrollar un nuevo lenguaje orientado a objetos. Este nombre tuvo
que ser cambiado debido a problemas de marca, pasando a llamarse C#.1 La
biblioteca de clases de la plataforma .NET fue migrada entonces al nuevo
lenguaje, este después fue modificado por Joseth M.

Hejlsberg lideró el proyecto de desarrollo de C#. Anteriormente, ya había


participado en el desarrollo de otros lenguajes como Turbo Pascal, Delphi y J++.

1 Juan González - Ryan León – Estiven Peña


Origen, evolución y características
técnicas del lenguaje de programación C#

Evolución del lenguaje C#

A principios de los 2000 Microsoft había liberado la primera gran versión del
lenguaje. Ha habido muchísimos cambios en los últimos 18 años. En este tiempo,
Java ha liberado 4 grandes versiones, mientras que C# ha liberado 6. Los
lenguajes han tomado caminos diferentes, y C# ha experimentado muchísima
innovación.

C# Versión 1

Cuando echamos la vista atrás, la primera versión de C# sí que se parecía un


montón a Java. Como parte de sus objetivos de diseño escritos para ECMA,
buscaba ser un "lenguaje orientado a objetos de uso general moderno y sencillo".
Pero si analizamos la versión 1.0 de C# 1.0 hoy, te marearías. Carecía de
capacidades asíncronas sólidas y de muchas de las "pulidas" funcionalidades
relacionadas con los genéricos que hoy en día damos por sentadas. En realidad,
carecía de genéricos en general. ¿Y LINQ? Nada. Eso tardaría aún unos cuantos
años en salir. La versión 1 de C# parecía estar bastante desprovista de
funcionalidad, comparado con hoy. Al final te veías escribiendo código pesado.
Pero bueno, como con cualquier versión 1.0 por algún lado hay que empezar.

C# Versión 2

Aquí las cosas se empiezan a poner interesantes. Repasemos algunas de las


principales características de C# 2.0, lanzado en 2005, junto con Visual Studio
2005

 Genéricos
 Tipos parciales
 Métodos anónimos
 Tipos anulables
 Iteradores
 Covarianza y contravarianza

2 Juan González - Ryan León – Estiven Peña


Origen, evolución y características
técnicas del lenguaje de programación C#

Aunque Microsoft puede que haya empezado con un lenguaje orientado a objetos
bastante genérico, la versión 2 de C# lo cambió todo enseguida. Se pusieron a la
tarea tras la salida de la versión inicial y fueron a por varias de las frustraciones
que causaba. Con genéricos, tienes tipos y métodos que pueden operar sobre un
tipo arbitrario mientras que aún conservan seguridad de tipos. Así, por ejemplo,
tener una List<T> te permite tener una List<string> o una List<int> y realizar
operaciones seguras de tipo en esas cadenas de caracteres o ints mientras iteras
por ellas.

La versión 2 de C# te permite iterar por los ítems de una Lista (u otros tipos
Enumerable) con un bucle foreach. Tener esto como un elemento de primera clase
del lenguaje mejoró ostensiblemente la legibilidad del código y la capacidad para
poder entenderlo.

C# Versión 3

La versión 3 de C# apareció a finales de 2007, junto con Visual Studio 2008,


aunque la funcionalidad completa aparecería con la versión 3.5 de C#. Algunas de
sus características principales en esta versión:

 Propiedades auto-implementadas
 Tipos anónimos
 Expresiones de consulta - LINQ
 Expresiones lambda
 Árboles de expresión
 Métodos de extensión

Microsoft había empezado a allanar el terreno para hacer de C# un lenguaje


funcional orientado a objetos híbrido. En concreto, con esta versión ya se podían
programar búsquedas declarativas tipo SQL para llevar a cabo operaciones en

3 Juan González - Ryan León – Estiven Peña


Origen, evolución y características
técnicas del lenguaje de programación C#
colecciones, entre otras cosas. En vez de tener que crear un bucle para computar
la media de una lista de enteros, ahora se podía hacer con algo tan fácil como
list.Average().

C# Versión 4

La versión 4 de C# nació con el estigma de no suponer una innovación rompedora


como sí lo había sido su antecesora versión 3. Y es que con la versión 3, Microsoft
hizo que el lenguaje dejase de estar a la sombra de Java y empezó a destacar.
Rápidamente el lenguaje se estaba convirtiendo en una opción elegante.

 Tipos dinámicos
 Argumentos opcionales y con nombre
 Covarianza y contravarianza genérica
 Tipos interop embebidos

Los tipos interop embebidos aliviaron problemas a la hora del despliegue. La


covarianza y contravarianza genéricas te dan mucha potencia, pero son
demasiado académicas y probablemente sean más valoradas entre los creadores
de frameworks y bibliotecas. Los argumentos opcionales y con nombre te permiten
eliminar muchas sobrecargas de método y ofrecen comodidad. Pero ninguna de
estas cosas altera el paradigma propiamente dicho. Con esta característica,
Microsoft introdujo en la versión 4 de C# la capacidad de anular el compilador al
tiparlo en tiempo de compilación. Es decir, al usar el tipo de referencia dinámico, te
puedes llegar a pegar un tiro en el pie como en los lenguajes de tipado dinámico
como JavaScript. Puedes crear una "x = cadena de caracteres" dinámica y luego
añadirle 6, dejando al tiempo de ejecución determinar qué diablos tiene que pasar
después.

4 Juan González - Ryan León – Estiven Peña


Origen, evolución y características
técnicas del lenguaje de programación C#

C# Versión 5

Con la versión 5 de C#, Microsoft liberó una versión con el foco muy puesto en la
innovación del lenguaje. Esta es la lista de las características más importantes:

 Programación asincrónica con Async y Await


 Atributos Caller info

El atributo caller info te permite recuperar información sobre el contexto en el que


estás sin tener que recurrir a un montón de código reflejo repetitivo. Async y await
tiene asincronía en el lenguaje como un participante de primera clase.

C# Versión 6

Con las versiones 3 y 5, Microsoft había hecho algunas cosas bastante


impresionantes en un lenguaje orientado a objetos (la versión 2 también, pero
estaban copiando conceptos de Java con esas funciones que introdujeron). Con la
versión 6 se alejaron de la idea de sacar una novedad dominante estrella y, en vez
de eso, liberaron muchas características para hacer felices a los usuarios del
lenguaje de programación. Aquí enumero unas cuantas:

 Importaciones estáticas (como en Java)


 Filtros de excepciones
 Inicializadores de propiedad
 Miembros con una expresión como cuerpo
 Propagador null
 Cadenas interpoladas
 Operador nameof
 Inicializador del diccionario
Si las vemos de forma individual, todas estas características del lenguaje son muy
interesantes. Pero si las valoramos en conjunto, observamos un patrón que nos
5 Juan González - Ryan León – Estiven Peña
Origen, evolución y características
técnicas del lenguaje de programación C#
llama la atención. En esta versión, Microsoft se ha esforzado en eliminar
repeticiones en el lenguaje y hacer que el código sea más ligero y legible. Así que
para los aficionados del código escueto y limpio, esta versión del lenguaje fue una
gran victoria.

C# Versión 7
Es la versión actual en la fecha que se ha escrito este artículo. Tiene cosas muy
chulas y revolucionarias que ya estaban en el ADN de la versión 6, pero sin el
compilador como servicio. Aquí van las novedades de esta versión:

 Variables out
 Tuplas y deconstrucción
 Coincidencia de patrones
 Funciones locales
 Extensión de la funcionalidad de miembros con una expresión como cuerpo
aparecida en C# 6
 Referencias locales y devoluciones

Microsoft dio solución a problemas que venían desde muy lejos al condensar la
declaración de variables que se pueden a usar con la palabra clave out y al
permitir valores de devolución múltiples vía tuplas. Además, Microsoft le dio un
uso más amplio al lenguaje. .NET ahora va dirigido a cualquier sistema operativo y
tiene la vista puesta de forma firme en la nube y en la portabilidad. Esto es lo que
más ocupa la mente y el tiempo de los diseñadores del lenguaje, además de
pensar en nuevas características. Ha habido 3 versiones secundarias desde C#
7.0: 7.1, 7.2, 7.3.

C# Versión 8

La versión 8.0 del lenguaje C# recoge las sugerencias de la comunidad de


desarrollo. Veamos algunas de las más sobresalientes:

6 Juan González - Ryan León – Estiven Peña


Origen, evolución y características
técnicas del lenguaje de programación C#
Tipos de Referencia Anulable (Nullable Reference Types): A diferencia de los tipos
por referencia, que pueden ser nulos sin problema, los tipos primitivos deben
contener algún valor correcto. Una de las características que se incorpora desde
C# 2.0 es la de que los tipos primitivos puedan ser asignados a null. En la versión
8.0, los tipos de referencia no serían más anulables por defecto. En lugar de esto
se

deberían marcar explícitamente utilizando la misma sintaxis "Tipo?" que se utiliza


para tipos de valor anulable.

Asignar un nulo a un tipo referencial no anulable generará una advertencia de


compilación. Igualmente, leer de un tipo anulable sería una advertencia de
compilador a menos que la variable en cuestión fuera explícitamente verificada en
su nulidad antes de accederla. En teoría pues, el único cambio que verían los
programadores es que tendrían que insertar algunos caracteres de interrogación
aquí y allá donde sea requerido. Pero una nueva sintaxis ha sido agregada a esta
característica. Considere un escenario donde se sabe que la variable anulable x
no es nula, pero no se le puede demostrar esto al compilador. En este caso se
puede usar x!.Method() para suprimir la advertencia de compilador acerca de
potenciales futuras referencias a nulo.

Streams Asincrónicas: Las streams asincrónicas son el equivalente asincrónico de


IEnumerable. Las streams asincrónicas es algo que se viene trabajando desde
2015. Después de mucho debate la sintaxis finalmente escogida es:

foreach await (string s in asyncstream). Cuando se define un iterador asincrónico,


se utilizaría esta firma de función:

async IAsyncEnumerable<T> MethodName()

Como con métodos IEnumerable normales, se puede usar "yield return" para
construir el stream.

7 Juan González - Ryan León – Estiven Peña


Origen, evolución y características
técnicas del lenguaje de programación C#
Implementaciones de interfaz por defecto: La implementaciones de interfaz por
defecto son esencialmente una forma limitada de herencia múltiple. Es permitirá
que interfaces abstractas definan completamente los métodos tal como las clases
abstractas. Sin embargo, las interfaces abstractas no serán capaces de declarar
constructores o campos.

Capítulo 2: Características técnicas

2.1. Características técnicas generales

Facilidad de uso

El ambiente de trabajo es muy cómodo ya que tiene un ambiente amigable y


clásico de las aplicaciones de Windows. En cuanto a la forma de programar, será
fácil de usar para quien está familiarizado con C++, ya que su estructuración
básica es muy similar, sin embargo C# ahorra muchos pasos “tediosos” de otros
lenguajes como la creación de funciones complejas desde cero y declaración de
variables globales.

Programación orientada a objetos

Esta forma de programación ahorra mucho código, lo cual indica que partes de
código son reutilizables para no volverlas a escribir, con lo cual se afirma que C#
presenta las características necesarias para considerarlo como un lenguaje
orientado a objetos, tales son: encapsulación, herencia y polimorfismo; además
una de las mejoras que presenta este lenguaje con respecto a este tipo de
programación es que para evitar confusiones no existen variables o funciones
globales, sino que se definen dentro de los tipos de datos. En cuanto a la
herencia, esta solo puede ser herencia simple, con lo cual se evitan confusiones
que si fuera herencia múltiple.
8 Juan González - Ryan León – Estiven Peña
Origen, evolución y características
técnicas del lenguaje de programación C#
Administración de memoria:
C# tiene la característica de inicializar los datos o variables declaradas en el
programa, además de que también de forma automática libera la memoria cuando
el mismo programa lo cree conveniente. Es decir tiene constructores y
destructores, y estos actúan automáticamente a menos que se manipulen desde el
código.

Seguridad en el manejo de datos:


C# tiene la característica de estar comprobando que efectivamente los tipos de
datos que se estén manejando correspondan a los validados para las funciones
que han sido creadas; así también vigila que no se produzcan errores en
operaciones matemáticas, además de que también impide el uso de variables que
no han sido inicializadas. Todo esto permite que no se produzcan errores en el
momento de la ejecución.

Sistema de tipos unificado:

Todos los tipos de datos que se definan siempre se derivarán, incluso de forma
implícita, de una clase base común llamada System.Object, por lo que dispondrán
de todos los miembros definidos en ésta clase. La ventaja de que todos los tipos
se deriven de una clase común es que facilita el diseño de colecciones genéricas
que puedan almacenar objetos de cualquier tipo.

Uso de operadores:
Este lenguaje permite de forma automática la manera en que pueden trabajar los
operadores, ya sea de tipo lógico, aritmético, etc. Es decir dependiendo del
contexto de donde se encuentre el operador, el programa detecta que tipo de uso
debe tener el operador.
9 Juan González - Ryan León – Estiven Peña
Origen, evolución y características
técnicas del lenguaje de programación C#
Compatible:
C# no sólo mantiene una sintaxis muy similar a C, C++ o Java que permite incluir
directamente en código escrito en C# fragmentos de código escrito en estos
lenguajes, sino que el runtime de lenguaje común también ofrece la posibilidad de
acceder a código nativo escrito como funciones sueltas no orientadas a objetos
tales como las DLLs de la API Win32.

Otras Características:

 Control de conversiones
 Control de inicialización de variables
 Control de índices en accesos a tablas
 Control de desbordamientos
 Control de tipos en “punteros a función”
 Control en parámetros múltiples
 Gestión automática de memoria
 Recolector de basura
 Liberación recursos determinista
 Extensibilidad de modificadores
 Versionable: Redefinir virtual con override

2.2. Entorno visual requerido


El entorno de C#.NET está compuesto con las herramientas necesarias que
continuación serán descritas:

10 Juan González - Ryan León – Estiven Peña


Origen, evolución y características
técnicas del lenguaje de programación C#
Cuadro de herramientas: El cuadro de herramientas contiene todas las
componentes visuales que nos permiten elaborar nuestro formulario.

Barra de Herramientas y menús: Proporciona paneles a cada lado del formulario


que puede contener uno o más controles ToolStrip, MenuStrip o StatusStrip.
ToolStripContainer añade la funcionalidad de interfaz de usuario.Sirve como una
forma de permitir ToolStrips (que contienen botones u otros controles) para
arrastrar alrededor de los bordes de un formulario. Se especifica cómo ToolStrips
pueden dividirse y organizarse. Sirve como contenedor de las barras de
herramientas. Con este control, puede organizar y cambiar las posiciones de las
barras de herramientas dentro de este contenedor. El ToolStripContainer se
compone deToolStripPanel s, que es el área real donde se coloca
el ToolStrip s. De forma predeterminada, hay cuatro paneles visibles a cada lado
de la ToolStripContainer.
11 Juan González - Ryan León – Estiven Peña
Origen, evolución y características
técnicas del lenguaje de programación C#
Nombre Descripción

Bottom Tool Strip Obtiene la parte inferior Tool Strip Panel de este


Panel control.

Bottom Tool Strip


Panel Visible Especifica si el fondo Tool Strip Panel es visible.

Content Panel Obtiene el panel central de este control.

Left Tool Strip Obtiene la izquierda Tool Strip Panel de este


Panel control.

Left Tool Strip


Panel Visible Especifica si el fondo Tool Strip Panel es visible.

Right Tool Strip


Panel Obtiene el derecho Tool Strip Panel de este control.

Right Tool Strip


PanelVisible Especifica si el derecho Tool Strip Panel es visible.

Top Tool Strip Obtiene la parte superior Tool Strip Panel de este


Panel control.

Top Tool Strip Especifica si la parte superior Tool Strip Panel es


Panel Visible visible.
 

Proyectos y propiedades: Los proyectos tienen propiedades que controlan


muchos aspectos de la compilación, la depuración, las pruebas y la
implementación. Algunas propiedades están presentes en todos los tipos de
proyecto, mientras que otras son exclusivas de plataformas o idiomas
específicos. Para acceder a las propiedades del proyecto, haga clic con el botón
derecho en el nodo del proyecto en el Explorador de soluciones y
elija Propiedades, o bien escriba "propiedades" en el cuadro de búsqueda Inicio
rápido de la barra de menús.

12 Juan González - Ryan León – Estiven Peña


Origen, evolución y características
técnicas del lenguaje de programación C#

Los proyectos de .NET también pueden tener un nodo de propiedades en el propio


árbol del proyecto.

Las propiedades del proyecto se organizan en grupos y cada grupo tiene su propia
página de propiedades. Es posible que las páginas varíen para lenguajes y tipos
de proyecto diferentes. En los proyectos de C#, F# y Visual Basic, las propiedades
se exponen en el Diseñador de proyectos. En la siguiente ilustración se muestra la
página Propiedad de compilación de un proyecto de WPF en C#:

13 Juan González - Ryan León – Estiven Peña


Origen, evolución y características
técnicas del lenguaje de programación C#

2.3. Tipos de datos


C# contiene veinte categorías generales de tipos de datos integrados: tipos de
valor y tipos de referencia. El término tipo de valor indica que esos tipos contienen
directamente sus valores. Tipos para definir números enteros:

14 Juan González - Ryan León – Estiven Peña


Origen, evolución y características
técnicas del lenguaje de programación C#

Tipo de datos de enteros

Tipo Equivalente BCL Tamaño Rango Significado

byte System.Byte Entero sin


8-bit (1-byte) 0 a 255
signo

sbyte System.SByte Entero con


8-bit (1-byte) -128 a 127
signo

short System.Int16 Entero corto


16-bit (2-byte) -32.768 a 32.767
con signo

ushort System.UInt16 Entero corto


16-bit (2-byte) 0 a 65.535
sin signo

int System.Int32 -2.147.483.648 a Entero medio


32-bit (4-byte)
2.147.483.647 con signo

uint System.UInt32 Entero medio


32-bit (4-byte) 0 a 4.294.967.295
sin signo

long System.Int64 -9.223.372.036.854.775.808 a Entero largo


64-bit (8-byte)
9.223.372.036.854.775.807 con signo

ulong System.UInt64 0a Entero largo


64-bit (8-byte)
18.446.744.073.709.551.615 sin signo

Los tipos de coma flotante pueden representar números con componentes


fraccionales. Existen dos clases de tipos de coma flotante: float y double. El
tipo double es el más utilizado porque muchas funciones matemáticas de la
biblioteca de clases de C# usan valores double. Quizá, el tipo de coma flotante
más interesante de C# es decimal, dirigido al uso de cálculos monetarios. La
15 Juan González - Ryan León – Estiven Peña
Origen, evolución y características
técnicas del lenguaje de programación C#
aritmética de coma flotante normal está sujeta a una variedad de errores de
redondeo cuando se aplica a valores decimales. El tipo decimal elimina estos
errores y puede representar hasta 28 lugares decimales.

Tipo de datos de coma flotante

Tipo Equivalente BCL Tamaño Rango Significado

float System.Single ±1.401298E−45 a Coma


32-bit (4-byte)
±3.402823E+38 flotante corto

±4.94065645841246E−
324 a Coma
double System.Double 64-bit (8-byte)
±1.79769313486232E+ flotante largo
308

−7.9228162514264337
Coma
decimal System.Decimal 593543950335 a
128-bit (16-byte) flotante
+7.9228162514264337
monetario
593543950335

Los caracteres en C# no tienen un tamaño de 8 bits como en muchos otros


lenguajes de programación, sino que usan un tamaño de 16 bits. Este tipo de dato
se llama char y utiliza la codificación Unicode. No existen conversiones
automáticas de tipo entero a char.

16 Juan González - Ryan León – Estiven Peña


Origen, evolución y características
técnicas del lenguaje de programación C#

Tipo de datos de caracteres

Tipo Equivalente BCL Tamaño Rango Significado

char System.Char 16-bit (2-byte) '\u0000'  a  '\uFFFF' Carácter unicode

Para los tipos de datos lógicos no existen conversiones automáticas de tipo entero


a bool.

Tipo de datos lógicos

Tipo Equivalente BCL Tamaño Rango Significado

8-bit (1- true  o  false


bool System.Boolean Verdadero o falso
byte)

Literales: En ocasiones, resulta más sencillo usar un sistema numérico en base


16 en lugar de 10, para tal caso C# permite especificar números enteros en

formato hexadecimal, y se define anteponiendo  0x , por ejemplo:  0xFF , que

equivale a  255  en decimal. C# tiene caracteres denominados secuencias de


escape para facilitar la escritura con el teclado de símbolos que carecen de
representación visual.

C#, al igual que C++, define un tipo de cadena de caracteres. Dentro de la cadena
de caracteres se pueden usar secuencias de escape. Una cadena de caracteres

puede iniciarse con el símbolo  @  seguido por una cadena entre comillas ( " ), en

17 Juan González - Ryan León – Estiven Peña


Origen, evolución y características
técnicas del lenguaje de programación C#
tal caso, las secuencias de escape no tienen efecto, y además la cadena puede
ocupar dos o más líneas.

Enteros

decimal 245 ,  [0..9]+

hexadecimal 0xF5 ,  0x[0..9, A..F, a..f]+

entero largo 12L

entero largo sin 654UL


signo

Coma flotante

float 23.5F ,  23.5f ;  1.72E3F ,  1.72E3f ,  1.72e3F ,  1.72e3f

Double 23.5 ,  23.5D ,  23.5d ,  1.72E3 ,  1.72E3D

decimal 9.95M

Caracteres

char 'a' ,  'Z' ,  '\u0231'

Cadenas

String "Hello, world" ;  "C:\\Windows\\" ,  @"C:\Windows\"

18 Juan González - Ryan León – Estiven Peña


Origen, evolución y características
técnicas del lenguaje de programación C#

Secuencias de escape

Alerta (timbre) \a

Retroceso \b

Avance de página \f

Nueva línea \n

Retorno de carro \r

Tabulador horizontal \t

Tabulador vertical \v

Nulo \0

Comilla simple \'

Comilla doble \"

Barra inversa \\

Variables: Las variables son identificadores asociados a valores. Se declaran


indicando el tipo de dato que almacenará y su identificador.

Un identificador puede:

19 Juan González - Ryan León – Estiven Peña


Origen, evolución y características
técnicas del lenguaje de programación C#
 empezar por "_".
 contener caracteres Unicode en mayúsculas y minúsculas (sensible a
mayúsculas y minúsculas).

Un identificador no puede:

 empezar por un número.


 empezar por un símbolo, ni aunque sea una palabra clave.
 contener más de 511 caracteres.

Declarar una variable:

int miNumero; // Declaramos la variable, pero no la inicializamos con


ningún valor.

Para asignar un valor a una variable, se indica el identificador de la misma,


seguido del símbolo igual (=) y el valor que queremos que almacene:

miNumero = 5; // Asignamos el valor '5' a la variable creada.

Se puede declarar y asignar un valor al mismo tiempo:

int miNumero = 5; // Declaramos la variable, y asignamos el valor '5'.

También puedes declarar una variable sin especificar el tipo de dato, utilizando el
mecanismo de inferencia mediante la palabra clave var donde el compilador
determina el tipo de dato que se le asignará a la variable y sólo es permitida para
variables locales, no para parámetros o datos miembro.

var cadena = "Esto es un string";

var numero1 = 5;

20 Juan González - Ryan León – Estiven Peña


Origen, evolución y características
técnicas del lenguaje de programación C#

var numero2 = 4.5;

var numero3 = 4.5D;

var objeto = new Object();

var resultado = Math.Pow(5, 2);

Constantes: Las constantes son valores inmutables, y por tanto no se pueden


cambiar.

const : Cuando se declara una constante con la palabra clave const, también se


debe asignar el valor. Tras esto, la constante queda bloqueada y no se puede
cambiar. Son implícitamente estáticas (static).

const double PI = 3.1415;

readonly: A diferencia de const, no requiere que se asigne el valor al mismo


tiempo que se declara. Pueden ser miembros de la instancia o miembros estáticos
de la clase (static).

readonly double E;
E = 2.71828;

Operadores: Los operadores aritméticos funcionan igual que en C y C++. El


resultado de los operadores relacionales y lógicos es un valor de tipo bool. Los
operadores de cortocircuito evalúan el segundo operando solo cuando es
necesario.

21 Juan González - Ryan León – Estiven Peña


Origen, evolución y características
técnicas del lenguaje de programación C#
Los operadores a nivel de bits no se pueden aplicar a tipos bool, float, double o
decimal.

Categoría Operadores

Aritméticos + - * / % Lógicos !   &&   ||

A nivel de bits & | ^ ~ Concatenación +

Incremento, ++   -- Desplazamiento <<   >>


decremento

Relacional ==   !=   <   >   <=   >= Asignación =  ^=   <<=   >>=

Acceso a . Indexación [ ]
miembro

Conversión ( ) Información de tipo as   is   sizeof   typeof

Condicional ?  :   ?? Creación de objeto new

22 Juan González - Ryan León – Estiven Peña


Origen, evolución y características
técnicas del lenguaje de programación C#
2.4. Conversiones de tipos
Las conversiones numéricas explícitas se utilizan para convertir cualquier tipo
numérico a cualquier otro tipo numérico, para el que no existe conversión implícita,
mediante una expresión que utilice el operador de conversión explícita. La
siguiente tabla muestra estas conversiones.

De Para

sbyte byte, ushort, uint, ulong o char

byte Sbyte o char

short sbyte, byte, ushort, uint, ulong o char

ushort sbyte, byte, short o char

int sbyte, byte, short, ushort, uint, ulong o char

uint sbyte, byte, short, ushort, int o char

long sbyte, byte, short, ushort, int, uint, ulong o char

ulong sbyte, byte, short, ushort, int, uint, long o char

char sbyte, byte o short

float sbyte, byte, short, ushort, int, uint, long, ulong, char o decimal

double sbyte, byte, short, ushort, int, uint, long, ulong, char, float o decimal

decimal sbyte, byte, short, ushort, int, uint, long, ulong, char, float o double

Las conversiones de tipo de variables en C# se representan en la siguiente tabla


en donde la fila es el origen y la columna el destino.

23 Juan González - Ryan León – Estiven Peña


Origen, evolución y características
técnicas del lenguaje de programación C#

Leyenda

Rojo Conversión incompatible (I).

Verd
Conversión automática o implícita (A).
e

Azul Conversión explícita (E).

Conversiones de tipo de datos

byte sbyte short ushort int uint long ulong float double decimal char bool

byte E A A A A A A E E E E I

sbyte E A E A E A A E E E E I

short E E E A A A A E E E E I

ushort E E E A A A A E E E E I

int E E E E E A A E E E E I

uint E E E E E A A E E E E I

long E E E E E E E E E E E I

ulong E E E E E E E E E E E I

float E E E E E E E E A E I I

double E E E E E E E E E E I I

24 Juan González - Ryan León – Estiven Peña


Origen, evolución y características
técnicas del lenguaje de programación C#

decimal E E E E E E E E E E I I

char E E E A A A A A A A A I

bool I I I I I I I I I I I I

 Toda conversión implícita no ocasiona pérdida de


información, truncamientos o redondeos.
 Es posible (pero no siempre ocurre) que en una conversión explícita haya
pérdida de información, truncamientos o redondeos.
 En toda conversión implícita el tipo de dato destino es mayor que el tipo de
dato origen.
 La conversión explícita se realiza indicando el tipo de dato al que se quiere
convertir entre paréntesis, seguido del valor:

long valor = 123; // Conversión implícita


long valor = (long)123; // Conversión explícita

Además de realizarse dentro de una asignación, las conversiones de tipos también


tienen lugar dentro de una expresión, pues en cada operación ambos operandos
deben de ser del mismo tipo. Si la conversión es del tipo implícito se efectúa el
siguiente algoritmo en dicho orden:

1. Si un operando es decimal, el otro operando se transforma a decimal.


2. Si un operando es double, el otro operando se transforma a double.
3. Si un operando es float, el otro operando se transforma a float.
4. Si un operando es ulong, el otro operando se transforma a ulong.
5. Si un operando es long, el otro operando se transforma a long.
6. Si un operando es uint, y si el otro operando es de tipo sbyte, short o int, los
dos se transforman a long.
7. Si un operando es uint, el otro operando se transforma a uint.
8. Si no es ninguno de los casos anteriores, los dos operandos se transforman
a int.

25 Juan González - Ryan León – Estiven Peña


Origen, evolución y características
técnicas del lenguaje de programación C#

2.5. Condicional
En C# contamos con varias de estas estructuras, así que las iremos explicando
con calma una a una, empezando en esta entrega con las estructuras
condicionales.  

Instrucción if...else if...else


 if significa si condicional, es decir, si te portas bien, te compro un helado y te dejo
ver la tele. Pues bien, en programación, es más o menos lo mismo. Pongamos un
poco de pseudo-código para que los principiantes se vayan haciendo a la idea:

 Si (te portas bien)


{
    te compro un helado;
    te dejo ver la tele;
}
 
En programación se evalúa a verdadero o falso la condición, que es lo que está
dentro de los paréntesis (en negrilla en el pseudo-código). Si esta condición se
evalúa a true (verdadero) se ejecutan las líneas del bloque, y si se evalúa a false
(falso) no se ejecutan. Vamos a verlo, ahora sí, en C#:

 
if (num==10)
{
    Console.WriteLine("El número es igual a 10");
}
 
Los programadores de C ó C++ dirán que la expresión siempre se evaluaría a
true, además de que se asignaría el valor 10 a la variable num. Pero este curso es
de C#, así que los programadores de C ó C++ se han vuelto a equivocar: en C# se
produciría un error, porque la expresión no se evalúa a true o false, sino que tiene
que retornar true o false necesariamente. Es decir, el compilador de C# no evalúa

26 Juan González - Ryan León – Estiven Peña


Origen, evolución y características
técnicas del lenguaje de programación C#
números como valores boolean. Esto hace que sea imposible equivocarse de
operador en expresiones de este tipo.

 
También puede ocurrir que tengamos que ejecutar una serie de acciones si se da
una condición y otras acciones en caso de que esa condición no se dé. Pues bien,
para eso tenemos la instrucción else. Volviendo a la interpretación lingüística para
favorecer todo esto a los principiantes, sería como un "de lo contrario", es
decir, si te portas bien, te compro un helado y te dejo ver la tele; de lo contrario, te
castigo en tu cuarto y te quedas sin cenar. ¿Quieres un poquito de pseudo-código
para ver esto? Venga, aquí lo tienes:

 
Si (te portas bien)
{
    te compro un helado;
    te dejo ver la tele;
}
de lo contrario
{
    te castigo en tu cuarto;
    te quedas sin cenar;
}
 

veamos algo de esto, ahora sí, en C#:

 
if (num==10)
{
    Console.WriteLine("El número es igual a 10");
}
else
{
    Console.WriteLine("El número no es igual a 10");
}
 

O bien:

 
if (num==10) Console.WriteLine("El número es igual a 10");
else Console.WriteLine("El número no es igual a 10");

27 Juan González - Ryan León – Estiven Peña


Origen, evolución y características
técnicas del lenguaje de programación C#
 

También podría suceder que hubiera que enlazar varios if con varios else.
Volvamos con otro ejemplo para ver si nos entendemos: si compras el libro te
regalo el separador, de lo contrario, si compras la pluma te regalo el cargador, de
lo contrario, si compras el cuaderno te regalo un llavero, y, de lo contario, no te
regalo nada. Veamos de nuevo el pseudo-código de esto:

 
Si (compras el libro)
{
    te regalo el separador;
}
de lo contrario si (compras la pluma)
{
    te regalo el cargador;
}
de lo contrario si (compras el cuaderno)
{
    te regalo un llavero;
}
de lo contrario
{
    no te regalo nada;
}
 
Esto es exactamente lo que ocurre en programación: el compilador no sigue
analizando las demás condiciones en el momento en el que encuentre una que
retorna true. Veamos algo de esto en C#:

 
if (num==10)
{
    Console.WriteLine("El número es igual a 10");
}
else if (num>5)
{
    Console.WriteLine("El número es mayor que 5");
}
else if (num>15)
{
    Console.WriteLine("El número es mayor que 15");
28 Juan González - Ryan León – Estiven Peña
Origen, evolución y características
técnicas del lenguaje de programación C#
}
else
{
    Console.WriteLine("El número no es 10 ni mayor que 5");
}
 
Instrucción switch
Una instrucción switch funciona de un modo muy similar a una construcción con
if...else if... else. Sin embargo, hay un diferencia que es fundamental: mientras en
las construcciones if...else if... else las condiciones pueden ser distintas en cada
uno de los if ... else if, en un switch se evalúa siempre la misma expresión,
comprobando todos los posibles resultados que esta pueda retornar. Un switch
equivaldría a comprobar las diferentes situaciones que se pueden dar con
respecto a una misma cosa.

Pongamos un poco de pseudo-código otra vez:

 
comprobemos (opcion)
{
    en caso de 1:
        te descuento un 10%;
        Nada más;
    en caso de 2:
        te descuento un 5%;
        Nada más;
    en caso de 3:
        te descuento un 2%;
        Nada más;
    en otro caso:
        no te descuento nada;
        Nada más;
}
 
Vamos a verlo en C#:

 
switch (opcion)
{
    case 1:
        descuento=10;
        break;
    case 2:
        descuento=5;
        break;
29 Juan González - Ryan León – Estiven Peña
Origen, evolución y características
técnicas del lenguaje de programación C#
    case 3:
        descuento=2;
        break;
    default:
        descuento=0;
        break;
}
 
switch (opcion)
{
    case 1:
        descuento=10;
        break;
    case 2:
        regalo="Cargador de CD"
    case 3:
        descuento=5;
        break;
    default:
        descuento=0;
        break;
}
 

switch (opcion)
{
    case 1:
        descuento=10;
        break;
    case 2:
    case 3:
        if (opcion==2) regalo="Cargador de CD";
        descuento=5;
        break;
    default:
        descuento=0;
        break;
}
 

30 Juan González - Ryan León – Estiven Peña


Origen, evolución y características
técnicas del lenguaje de programación C#

2.6. Objetos y clases


Los objetos, clases y estructuras tienen las propiedades siguientes:
 Los objetos son instancias de un tipo de datos determinado. El tipo de datos
proporciona un plano para el objeto que se crea, o del cual se crean
instancias, cuando se ejecuta la aplicación.
 Los nuevos tipos de datos se definen mediante clases y estructuras.
 Las clases y estructuras conforman las unidades de creación de
aplicaciones de C#, ya que contienen código y datos. Una aplicación de C#
siempre contendrá al menos una clase.
 Una estructura se puede considerar una clase ligera, idónea para crear
tipos de datos que almacenan pequeñas cantidades de datos, y no
representa un tipo que después se podría extender por medio de la
herencia.
 Las clases de C# son compatibles con la herencia, lo que significa que se
pueden derivar de una clase previamente definida.

Las clases en C# se definen de forma parecida a los registros (struct), sólo que
ahora, además de variables (que representan sus detalles internos, y que
llamaremos sus "atributos"), también incluirán funciones (las acciones que puede
realizar ese objeto, que llamaremos sus "métodos"). Atributos y métodos formarán
parte de "un todo", en vez de estar separados en distintas partes del programa.
Esto es lo que se conoce como "Encapsulación".

31 Juan González - Ryan León – Estiven Peña


Origen, evolución y características
técnicas del lenguaje de programación C#

Así, una clase "Puerta" se podría declarar así:

public class Puerta


{
 
int ancho; // Ancho en centimetros
int alto; // Alto en centimetros
int color; // Color en formato RGB
bool abierta; // Abierta o cerrada
 
public void Abrir()
{
abierta = true;
}
 
public void Cerrar()
{
abierta = false;
}
 
public void MostrarEstado()
{
Console.WriteLine("Ancho: {0}", ancho);
Console.WriteLine("Alto: {0}", alto);
Console.WriteLine("Color: {0}", color);
Console.WriteLine("Abierta: {0}", abierta);
}
 
} // Final de la clase Puerta

32 Juan González - Ryan León – Estiven Peña


Origen, evolución y características
técnicas del lenguaje de programación C#
 

Como se puede observar, los objetos de la clase "Puerta" tendrán un ancho, un


alto, un color, y un estado (abierta o no abierta), y además se podrán abrir o cerrar
(y además, nos pueden "mostrar su estado", para comprobar que todo funciona
correctamente).

Para declarar estos objetos que pertenecen a la clase "Puerta", usaremos la


palabra "new", igual que hacíamos con los "arrays":

ejemplo = new int[4];

Cuando sepamos cuantos datos vamos a guardar (por ejemplo 4), podremos
reservar espacio con la orden "new", así:

Puerta p = new Puerta();


p.Abrir();
p.MostrarEstado();

Vamos a completar un programa de prueba que use un objeto de esta clase (una
"Puerta"), muestre su estado, la abra y vuelva a mostrar su estado:

// Ejemplo_06_02a.cs
// Primer ejemplo de clases
// Introducción a C#, por Nacho Cabanes
 
using System;
 
public class Puerta
{
  int ancho; // Ancho en centimetros

33 Juan González - Ryan León – Estiven Peña


Origen, evolución y características
técnicas del lenguaje de programación C#
int alto; // Alto en centimetros
int color; // Color en formato RGB
bool abierta; // Abierta o cerrada
 
public void Abrir()
{
abierta = true;
}
  public void Cerrar()
{
abierta = false;
}
  public void MostrarEstado()
{
Console.WriteLine("Ancho: {0}", ancho);
Console.WriteLine("Alto: {0}", alto);
Console.WriteLine("Color: {0}", color);
Console.WriteLine("Abierta: {0}", abierta);
}
 } // Final de la clase Puerta
  public class Ejemplo_06_02a
{
  public static void Main()
{
Puerta p = new Puerta();
 
Console.WriteLine("Valores iniciales...");
p.MostrarEstado();
 
Console.WriteLine();
 
Console.WriteLine("Vamos a abrir...");
p.Abrir();
p.MostrarEstado();

34 Juan González - Ryan León – Estiven Peña


Origen, evolución y características
técnicas del lenguaje de programación C#
}
 } 

Este fuente ya no contiene una única clase (class), como todos nuestros ejemplos
anteriores, sino dos clases distintas:

 La clase "Puerta", que es el nuevo objetos con el que vamos a practicar.


 La clase "Ejemplo_06_02a", que representa a nuestra aplicación.

(Nota: al compilar, puede que obtengas algún "Aviso" -warning- que te dice que
has declarado "alto", "ancho" y "color", pero no las estás utilizando; no es
importante por ahora, puedes ignorar ese aviso).

El resultado de ese programa es el siguiente:

Valores iniciales...
Ancho: 0
Alto: 0
Color: 0
Abierta: False
 
Vamos a abrir...
Ancho: 0
Alto: 0
Color: 0
Abierta: True

Se puede ver que en C# (pero no en todos los lenguajes), las variables que
forman parte de una clase (los "atributos") tienen un valor inicial predefinido: 0
para los números, una cadena vacía para las cadenas de texto, "false" para los
datos booleanos.

35 Juan González - Ryan León – Estiven Peña


Origen, evolución y características
técnicas del lenguaje de programación C#

Vemos también que se accede a los métodos y a los datos precediendo el nombre
de cada uno por el nombre de la variable y por un punto, como hacíamos con los
registros (struct).

Aun así, en nuestro caso no podemos hacer directamente "p.abierta = true" desde
el programa principal, por dos motivos:

Por ejemplo, para conocer y modificar los valores del "ancho" de una puerta,
podríamos crear un método LeerAncho, que nos devolviera su valor, y un método
CambiarAncho, que lo reemplazase por otro valor. No hay un convenio claro sobre
cómo llamar a a estos métodos en español, por lo que es frecuente usar las
palabras inglesas "Get" y "Set" para leer y cambiar un valor, respectivamente. Así,
crearemos funciones auxiliares GetXXX y SetXXX que permitan acceder al valor
de los atributos (en C# existe una forma alternativa de hacerlo, usando
"propiedades", que veremos más adelante):

public int GetAncho()


{
return ancho;
}
 
public void SetAncho(int nuevoValor)
{
ancho = nuevoValor;
}

Así, una nueva versión del programa, que incluya ejemplos de Get y Set,
podría ser:

// Ejemplo_06_02b.cs

36 Juan González - Ryan León – Estiven Peña


Origen, evolución y características
técnicas del lenguaje de programación C#
// Clases, get y set
// Introducción a C#, por Nacho Cabanes
 
using System;
 
public class Puerta
{
 
int ancho; // Ancho en centimetros
int alto; // Alto en centimetros
int color; // Color en formato RGB
bool abierta; // Abierta o cerrada
 
public void Abrir()
{
abierta = true;
}
 
public void Cerrar()
{
abierta = false;
}
 
public int GetAncho()
{
return ancho;
}
 
public void SetAncho(int nuevoValor)
{
ancho = nuevoValor;
}
 
public void MostrarEstado()

37 Juan González - Ryan León – Estiven Peña


Origen, evolución y características
técnicas del lenguaje de programación C#
{
Console.WriteLine("Ancho: {0}", ancho);
Console.WriteLine("Alto: {0}", alto);
Console.WriteLine("Color: {0}", color);
Console.WriteLine("Abierta: {0}", abierta);
}
 
} // Final de la clase Puerta
 
public class Ejemplo_06_02b
{
 
public static void Main()
{
Puerta p = new Puerta();
 
Console.WriteLine("Valores iniciales...");
p.MostrarEstado();
 
Console.WriteLine();
 
Console.WriteLine("Vamos a abrir...");
p.Abrir();
p.SetAncho(80);
p.MostrarEstado();
}
 
}
 

También puede desconcertar que en "Main" aparezca la palabra "static", mientras


que no lo hace en los métodos de la clase "Puerta". Veremos el motivo un poco
más adelante, pero de momento perderemos la costumbre de escribir "static"
antes de

38 Juan González - Ryan León – Estiven Peña


Origen, evolución y características
técnicas del lenguaje de programación C#

cada función: a partir de ahora, sólo Main será "static". Aunque a veces se usan
indistintamente, una clase y un objeto son cosas diferentes. Una clase define un
tipo de objeto, pero no es un objeto en sí. Un objeto es una entidad concreta
basada en una clase y, a veces, se conoce como una instancia de una clase.

Los objetos se pueden crear usando la palabra clave new, seguida del nombre de
la clase en la que se basará el objeto, como en este ejemplo:
C#Copiar
Customer object1 = new Customer();

Cuando se crea una instancia de una clase, se vuelve a pasar al programador una
referencia al objeto. En el ejemplo anterior, object1 es una referencia a un objeto
que se basa en Customer.Esta referencia apunta al objeto nuevo, pero no
contiene los datos del objeto. De hecho, puede crear una referencia de objeto sin
tener que crear ningún objeto:
C#Copiar
Customer object2;

No se recomienda crear referencias de objeto como esta, que no hace referencia a


ningún objeto, ya que, si se intenta obtener acceso a un objeto a través de este
tipo de referencia, se producirá un error en tiempo de ejecución. Pero dicha
referencia puede haberse creado para hacer referencia a un objeto, ya sea
creando un nuevo objeto o asignándola a un objeto existente, como en el siguiente
ejemplo:
C#Copiar
Customer object3 = new Customer();
Customer object4 = object3;

Este código crea dos referencias de objeto que hacen referencia al mismo
objeto. Por lo tanto, los cambios efectuados en el objeto mediante object3 se

39 Juan González - Ryan León – Estiven Peña


Origen, evolución y características
técnicas del lenguaje de programación C#
reflejan en los usos posteriores de object4.Dado que los objetos basados en
clases se tratan por referencia, las clases se denominan "tipos de referencia".

2.7. Modularidad y encapsulamiento


El concepto de módulo no es exclusivo del modelo OO, pero encuentra en
el mismo un buen soporte y aplicación. Particularmente el concepto de
namespace es un ejemplo muy representativo del concepto de módulo, es por ello
que se le dedica de manera muy breve esta sección a este último concepto.

“En un sentido los módulos pueden considerarse simplemente como una técnica
mejorada para crear y manejar espacios de nombres” [1] (namespaces). En este
sentido una aplicación importante del concepto de módulo es para la creación de
bibliotecas de clases, es decir, un espacio de nombres que va a contener
diferentes clases.

En el sentido más amplio, un módulo es un “contenedor” de código que permite


mejorar la estructura y organización de las aplicaciones de software. Una clara
aplicación del concepto de módulo puede verse a través de las propias clases.
“Una clase será a su vez un módulo y un tipo. Como módulo la clase encapsula
(encierra) un número de facilidades o recursos que ofrecerá a otras clases (sus
clientes). Como tipo describe un conjunto de objetos, instancias o ejemplares que
existirán en tiempo de ejecución.

Una de las maneras más eficientes de mantener la seguridad en las aplicaciones


Web y de Escritorio en cualquier lenguaje de programación es
el Encapsulamiento, además de brindar seguridad a las aplicaciones permite tener
una organización muy precisa a la hora de desarrollar sin embargo en muchas
ocasiones se vuelve tedioso manejar todos los métodos de encapsulamiento de un
objeto, en especial cuando son muchos los atributos de la clase.

40 Juan González - Ryan León – Estiven Peña


Origen, evolución y características
técnicas del lenguaje de programación C#
Empecemos por definir ciertos conceptos básicos de la programación orientada a
objetos (POO).

Está compuesta por clases, una clase en términos coloquiales, es el plano de un


objeto, es donde se deben definir todas las características de los
objetos de la vida real o de objetos abstractos, en POO siempre se habla de dos
conceptos claves: Atributos y Métodos.

Atributos: Son las características de los objetos, por ejemplo, los atributos de una
persona son, nombre, apellidos, número de documento, estatura, color de piel,
peso, etcétera.

Métodos: Son las funciones o acciones del objeto en caso de la persona, los


métodos son, caminar, hablar, reír, pensar, gritar, etcétera.

Una de las premisas de POO, es que la mayoría, sino todos, los atributos de un
objeto deben ser privados, esto para tener seguridad sobre los valores del objeto,
pero entonces...¿cómo acceder a los atributos de una clase?, la
respuesta, encapsulamiento, los métodos de encapsulamiento se utilizan sólo
cuando es apropiado entregar los datos a otro objeto que solicite la información.

Básicamente, el encapsulamiento se usa para dar más seguridad en tus


aplicaciones, para evitar que la información se filtre y para dar mucho más orden
en las clases.

41 Juan González - Ryan León – Estiven Peña


Origen, evolución y características
técnicas del lenguaje de programación C#

2.8. Herencia
En orientación a objetos la herencia es el mecanismo fundamental para
implementar la reutilización y extensibilidad del software. A través de ella los
diseñadores pueden construir nuevas clases partiendo de una jerarquía de clases
ya existente (comprobadas y verificadas) evitando con ello el rediseño, la
remodificación y verificación de la parte ya implementada. La herencia facilita la
creación de objetos a partir de otros ya existentes, obteniendo características
(métodos y atributos) similares a los ya existentes.

Una relación de generalización trae varias consecuencias y una de ellas es


precisamente la herencia: la clase derivada hereda todos los miembros (campos,
propiedades y métodos) de la clase base.

Este es un punto importante: la herencia no es herencia sólo de interfaz sinó


también de implementación. Es decir, si tengo mi clase:

class Coche : Vechiculo


{
public string Marca { get { ... } }
public string Modelo { get { ... } }
}

Un Coche es un Vehículo que además tiene una Marca y un Modelo. Así yo puedo
hacer:

Coche c = new Coche();


c.Acelerar(100);
// A que velocidad va mi coche?
int velocidad = c.Velocidad;
// Es un SEAT?
if (c.Marca == "SEAT") { ... }
42 Juan González - Ryan León – Estiven Peña
Origen, evolución y características
técnicas del lenguaje de programación C#

Fijaos que puedo llamar a la propiedad Marca (definida en la propia clase Coche)


para evaluar de que marca es mi coche, pero también puedo llamar al
método Acelerar y a la propiedad Velocidad. Así pues la clase Coche obtiene “una
copia” de todos los métodos y propiedades de la clase de la cual deriva (su clase
base) y además puede añadir métodos o propiedades nuevos. Eso es, ni más ni
menos lo que entendemos por herencia. Es importante que os quedéis con la idea
de que la clase derivada obtiene una copia de los métodos y propiedades
heredados porque así podréis entender el Problema de la herencia múltiple. C# (al
igual que Java) es un lenguaje con herencia simple. Eso significa que una
clase sólo puede derivar de una clase base a la vez.

La herencia en programación orientada a objetos nos permite generar una


funcionalidad de una clase existente al crear una nueva clase que derive de ella.

En c# no se permite la herencia múltiple, lo que quiere decir que no se puede


heredar de mas de una clase a la vez; si lo vemos de una forma sencilla la
herencia no es mas que la facultad de un objeto de heredar características de otro.

¿por que se hereda?; si lo vemos del lado de programación es para poder utilizar
métodos, propiedades (campos) y variables de la clase padre en el la clase hijo.

Comencemos con un ejemplo muy simple de herencia, tengo las siguientes clases
que tomare para mi ejemplo.

43 Juan González - Ryan León – Estiven Peña


Origen, evolución y características
técnicas del lenguaje de programación C#

Tenemos una clase Profesor que hereda de la clase Personal ya echa quedaran
de esta forma:

44 Juan González - Ryan León – Estiven Peña


Origen, evolución y características
técnicas del lenguaje de programación C#

La clase tendrá tres atributos Id, Nombre y Apellido, y un constructor. Ahora lo que
haremos será que profesor herede de la clase Personal de esta forma:

45 Juan González - Ryan León – Estiven Peña


Origen, evolución y características
técnicas del lenguaje de programación C#

Para hacer una herencia en c# entre dos clase solo hay que utilizar los dos puntos
seguidos del nombre de la clase padre.

Hoy solo hace falta crear el constructor que me tome los parámetros de la clase
padre de esta forma.

Para decirle que tome los atributos de la clase padre haremos uso de la palabra
clave base  y tenemos que colocar los parámetros que tenga la clase padre.

Como puedes ver no tengo atributos en la case hijo, ahora solo tengo que hacer
esto en el Program de la aplicación de consola.

46 Juan González - Ryan León – Estiven Peña


Origen, evolución y características
técnicas del lenguaje de programación C#
Como podemos apreciar aunque la clase profesor no contiene campos como
hereda de la clase personal contiene los campos del padre si los llenamos no
habrá problemas.

En este momento también podríamos llenar la clase personal y no tendríamos


problemas al hacerlo.

Solo hace falta mostrarlos en la consola de esta forma:

47 Juan González - Ryan León – Estiven Peña


Origen, evolución y características
técnicas del lenguaje de programación C#

Nos mostraría esto:

48 Juan González - Ryan León – Estiven Peña


Origen, evolución y características
técnicas del lenguaje de programación C#
Para comprobar que la clase hijo es independiente de la clase padre
modificaremos al hijo agregándole un campo más el cual será la dirección
quedando así:

Si nos vamos al program ahora la clase hijo profesor dará un error.

49 Juan González - Ryan León – Estiven Peña


Origen, evolución y características
técnicas del lenguaje de programación C#
Esto se da por que ahora tiene los atributos del padre además de uno propio,
corrijamos ese error agregando el nuevo atributo y vemos el resultado en consola.

Miremos que en este momento la clase hijo tiene un atributo mas que la clase
padre, lo cual nos da otra característica nueva del hijo que no tiene el padre.
Corramos esto y veamos el cambio.

50 Juan González - Ryan León – Estiven Peña


Origen, evolución y características
técnicas del lenguaje de programación C#
Como comentamos al principio es posible heredar muchas características del
padre en el hijo veamos unas de ellas, primero es posible utilizar variables que
fueron inicializadas en el padre atraves del hijo veamos creemos una variable en
Personal:

En la clase padre inicialice esta variable hoy podemos hacer esto en el program.

Si corremos esto dará lo siguiente:

51 Juan González - Ryan León – Estiven Peña


Origen, evolución y características
técnicas del lenguaje de programación C#
Y por ultimo para terminar veamos como se trata un método en este tipo de
asociación. Primero crearemos un método en la clase personal como lo hicimos
con la variable.

Este método solo me permitirá sumar dos números pero en la clase Profesor
quiero que me sume tres de esta forma:

52 Juan González - Ryan León – Estiven Peña


Origen, evolución y características
técnicas del lenguaje de programación C#

Como se puede ver en las imágenes puedo utilizar el método del padre y el que
modifique en el hijo esto se debe a que ahora el método esta sobrecargado,
utilizare el que modifique en el hijo el cual que me suma tres números:
53 Juan González - Ryan León – Estiven Peña
Origen, evolución y características
técnicas del lenguaje de programación C#

Si lo corremos se vería lo siguiente;

54 Juan González - Ryan León – Estiven Peña


Origen, evolución y características
técnicas del lenguaje de programación C#

2.9. Clases abstractas

Las clases abstractas son aquellas que por sí mismas no se pueden identificar con
algo 'concreto' (no existen como tal en el mundo real), pero sí poseen
determinadas características que son comunes en otras clases que pueden ser
creadas a partir de ellas.

Para que lo comprendas mejor, un ejemplo de clase abstracta sería una llamada
Vehículo: todos ellos realizan acciones similares (arrancar, acelerar, frenar, etc.),
pero sin embargo existen muchos tipos de vehículos diferentes y que se
comportan de forma totalmente distinta (el proceso de arrancarlos no se realiza
siguiendo los mismos pasos, unos tienen que despegar y vuelan como los
aviones, otros se sumergen para desplazarse por debajo del agua como los
submarinos, cada uno de ellos necesita ser frenado de distinto modo...).

Es decir, en el mundo real no existe un objeto 'vehículo' como tal sino que hay
diferentes tipos de vehículo, pero aunque poseen características comunes y
realizan las mismas acciones lo hacen de forma muy diferente (pudiendo además
realizar otras específicas cada uno de ellos).

Así pues, ya que una clase abstracta no representa algo concreto tampoco puede
ser instanciada (no se puede crear un Objeto a partir de ella) pero sí es posible
crear otras clases en base a su definición.

public abstract class Animal

{
private String nombre;
// ----------------------
public Animal() {
}
55 Juan González - Ryan León – Estiven Peña
Origen, evolución y características
técnicas del lenguaje de programación C#
// ----------------------
public String getNombre() {
return this.nombre;
}
// ----------------------
public void setNombre( String nombre ) {
this.nombre = nombre;
}
// ----------------------
public void comer() {
System.out.println( this.getNombre() + " está comiendo...");
}
// ----------------------
public void caminar() {
System.out.println( this.getNombre() + " está caminando...");
}
// ----------------------
// Este método deberá ser compartido por las clases que hereden
}

2.10. Polimorfismo
El polimorfismo suele considerarse el tercer pilar de la programación orientada a
objetos, después de la encapsulación y la herencia. Polimorfismo es una palabra
griega que significa "con muchas formas" y tiene dos aspectos diferentes:

En tiempo de ejecución, los objetos de una clase derivada pueden ser tratados
como objetos de una clase base en lugares como parámetros de métodos y
colecciones o matrices. Cuando ocurre, el tipo declarado del objeto ya no es
idéntico a su tipo en tiempo de ejecución.

56 Juan González - Ryan León – Estiven Peña


Origen, evolución y características
técnicas del lenguaje de programación C#

Las clases base pueden definir e implementar métodos virtuales, y las clases
derivadas pueden invalidarlos, lo que significa que pueden proporcionar su propia
definición e implementación. En tiempo de ejecución, cuando el código de cliente
llama al método, CLR busca el tipo en tiempo de ejecución del objeto e invoca esa
invalidación del método virtual. Por lo tanto, en el código fuente puede llamar a un
método en una clase base y hacer que se ejecute una versión del método de la
clase derivada.

Los métodos virtuales permiten trabajar con grupos de objetos relacionados de


manera uniforme. Por ejemplo, supongamos que tiene una aplicación de dibujo
que permite a un usuario crear varios tipos de formas en una superficie de dibujo.
En tiempo de compilación, no sabe qué tipos específicos de formas creará el
usuario. Sin embargo, la aplicación tiene que realizar el seguimiento de los
distintos tipos de formas que se crean, y tiene que actualizarlos en respuesta a las
acciones del mouse del usuario. Para solucionar este problema en dos pasos
básicos, puede usar el polimorfismo:

Crear una jerarquía de clases en la que cada clase de forma específica deriva de
una clase base común.

Usar un método virtual para invocar el método apropiado en una clase derivada
mediante una sola llamada al método de la clase base.

Primero, cree una clase base llamada Shape y clases derivadas como Rectangle,
Circle y Triangle. Dé a la clase Shape un método virtual llamado Draw e invalídelo
en cada clase derivada para dibujar la forma determinada que la clase representa.
Cree un objeto List<Shape> y agregue Circle, Triangle y Rectangle a él. Para
actualizar la superficie de dibujo, use un bucle foreach para iterar por la lista y
llamar al método Draw en cada objeto Shape de la lista. Aunque cada objeto de la
lista tenga un tipo declarado de Shape, se invocará el tipo en tiempo de ejecución
(la versión invalidada del método en cada clase derivada).

57 Juan González - Ryan León – Estiven Peña


Origen, evolución y características
técnicas del lenguaje de programación C#
Veamos un ejemplo:

using System;
using System.Collections.Generic;

public class Shape


{
// A few example members
public int X { get; private set; }
public int Y { get; private set; }
public int Height { get; set; }
public int Width { get; set; }

// Virtual method
public virtual void Draw()
{
Console.WriteLine("Performing base class drawing tasks");
}
}

class Circle : Shape


{
public override void Draw()
{
// Code to draw a circle...
Console.WriteLine("Drawing a circle");
base.Draw();
}
}

58 Juan González - Ryan León – Estiven Peña


Origen, evolución y características
técnicas del lenguaje de programación C#
class Rectangle : Shape
{
public override void Draw()
{
// Code to draw a rectangle...
Console.WriteLine("Drawing a rectangle");
base.Draw();
}
}
class Triangle : Shape
{
public override void Draw()
{
// Code to draw a triangle...
Console.WriteLine("Drawing a triangle");
base.Draw();
}
}

class Program
{
static void Main(string[] args)
{
// Polymorphism at work #1: a Rectangle, Triangle and Circle
// can all be used whereever a Shape is expected. No cast is
// required because an implicit conversion exists from a derived
// class to its base class.
var shapes = new List<Shape>

59 Juan González - Ryan León – Estiven Peña


Origen, evolución y características
técnicas del lenguaje de programación C#
{
new Rectangle(),
new Triangle(),
new Circle()
};

// Polymorphism at work #2: the virtual method Draw is


// invoked on each of the derived classes, not the base class.
foreach (var shape in shapes)
{
shape.Draw();
}

// Keep the console open in debug mode.


Console.WriteLine("Press any key to exit.");
Console.ReadKey();
}

/* Output:
Drawing a rectangle
Performing base class drawing tasks
Drawing a triangle
Performing base class drawing tasks
Drawing a circle
Performing base class drawing tasks
*/

60 Juan González - Ryan León – Estiven Peña


Origen, evolución y características
técnicas del lenguaje de programación C#

2.11. Interfaces
En teoría de orientación a objetos, la interfaz de una clase es todo lo que podemos
hacer con ella. A efectos prácticos: todos los métodos, propiedades y variables
públicas (aunque no deberían haber nunca variables públicas, debemos usar
propiedades en su lugar) de la clase conforman su interfaz.

Dada la siguiente clase:

class Contenedor
{
public int Quitar();
public void Meter(int v);
private bool EstaRepetido(int v);
}

Su interfaz está formada por los métodos Quitar y Meter. El método EstaRepetido
no forma parte de la interfaz de dicha clase, ya que es privado.

En orientación a objetos decimos que la interfaz de una clase define el


comportamiento de dicha clase, ya que define que podemos y que no podemos
hacer con objetos de dicha clase: dado un objeto de la clase Contenedor yo puedo
llamar al método Quitar y al métdo Meter pero no puedo llamar al método
EstaRepetido.

Así pues: toda clase tiene una interfaz que define que podemos hacer con los
objetos de dicha clase.

61 Juan González - Ryan León – Estiven Peña


Origen, evolución y características
técnicas del lenguaje de programación C#

2.12. Excepciones y Ciclo While

En C#, los errores del programa en tiempo de ejecución se propagan a través del
programa mediante un mecanismo denominado excepciones. Las excepciones las
inicia el código que encuentra un error y las detecta el código que puede corregir
dicho error. Las excepciones puede iniciarlas .NET Framework Common
Language Runtime o el código de un programa. Una vez iniciada, una excepción
se propaga hasta la pila de llamadas hasta que encuentra una instrucción catch
para la excepción. Las excepciones no detectadas se controlan mediante un
controlador de excepciones que ofrece el sistema y muestra un cuadro de diálogo.

Las excepciones están representadas por clases derivadas deExceptopn. Esta


clase identifica el tipo de excepción y contiene propiedades que tienen los detalles
sobre la excepción. Iniciar una excepción implica crear una instancia de una clase
derivada de excepción, configurar opcionalmente las propiedades de la excepción
y luego producir el objeto con la palabra clave throw. Por ejemplo:

class CustomException : Exception


{
public CustomException(string message)
{
}
}
private static void TestThrow()
{
CustomException ex =
new CustomException("Custom exception in TestThrow()");

throw ex;
}
62 Juan González - Ryan León – Estiven Peña
Origen, evolución y características
técnicas del lenguaje de programación C#

Cuando se inicia una excepción, el entorno runtime comprueba la instrucción


actual para ver si se encuentra dentro de un bloque try. Si es así, se comprueban
los bloques catch asociados al bloque try para ver si pueden detectar la excepción.
Los bloques Catch suelen especificar tipos de excepción; si el tipo del bloque
catch es el mismo de la excepción, o una clase base de la excepción, el bloque
catch puede controlar el método. Por ejemplo:

static void TestCatch()


{
try
{
TestThrow();
}
catch (CustomException ex)
{
System.Console.WriteLine(ex.ToString());
}
}

Si la instrucción que inicia una excepción no está en un bloque try o si el bloque try
que la encierra no tiene un bloque catch coincidente, el entorno runtime busca una
instrucción try y bloques catch en el método de llamada. El entorno runtime sigue
hasta la pila de llamadas para buscar un bloque catch compatible. Después de
encontrar el bloque catch y ejecutarlo, el control pasa a la siguiente instrucción
después de dicho bloque catch. Una instrucción try puede contener más de un
bloque catch. Se ejecuta la primera instrucción catch que pueda controlar la
excepción; las instrucciones catch siguientes se omiten, aunque sean compatibles.
Por consiguiente, los bloques catch deben ordenarse siempre de más específico
(o más derivado) a menos específico. Por ejemplo:

63 Juan González - Ryan León – Estiven Peña


Origen, evolución y características
técnicas del lenguaje de programación C#

Ciclo while
La instrucción while ejecuta una instrucción o un bloque de instrucciones mientras
una expresión booleana especificada se evalúa como true. Como esa expresión
se evalúa antes de cada ejecución del bucle, un bucle while se ejecuta cero o
varias veces. Esto es diferente del bucle do que se ejecuta una o varias veces.

En cualquier punto del bloque de instrucciones while, se puede salir del bucle
mediante la instrucción break.

Puede ir directamente a la evaluación de la expresión while mediante la


instrucción continue. Si la expresión se evalúa como true, la ejecución continúa en
la primera instrucción del bucle. En caso contrario, la ejecución continúa en la
primera instrucción después del bucle.

También se puede salir de un bucle while mediante las instrucciones goto, return o
throw.

En el ejemplo siguiente se muestra el uso de la instrucción while. Haga clic en


Ejecutar para ejecutar el código de ejemplo. Después, puede modificar el código y
volver a ejecutarlo.

int n = 0;
while (n < 5)
{
Console.WriteLine(n);
n++;
}

64 Juan González - Ryan León – Estiven Peña


Origen, evolución y características
técnicas del lenguaje de programación C#

2.13. Arreglos
Antes de comenzar a explicaros con mayor claridad qué es un array quiero
advertir nuevamente a los programadores de C/C++: En C#, aunque parecidos, los
arrays son diferentes tanto semántica como sintácticamente, de modo que te
recomiendo que no pases por alto esta entrega.

Bien, una vez hechas todas las aclaraciones previas, creo que podemos
comenzar. Un array es un indicador que puede almacenar varios valores
simultáneamente. Cada uno de estos valores se identifica mediante un número al
cual se llama índice. Así, para acceder al primer elemento del array habría que
usar el índice cero, para el segundo el índice uno, para el tercero el índice dos, y
así sucesivamente. Que nadie se preocupe si de momento todo esto es un poco
confuso, ya que lo voy a ir desmenuzando poco a poco. Vamos a ver cómo se
declara un array:

 tipo[] variable;
Bien, como veis es muy parecido a como se declara una variable normal, sólo que
hay que poner corchetes detrás del tipo. Los programadores de C/C++ habrán
observado inmediatamente la diferencia sintáctica. En efecto, en la declaración de
un array en C# los corchetes se colocan detrás del tipo y no detrás de la variable.
Esta pequeña diferencia sintáctica se debe a una importante diferencia semántica:
aquí los arrays son objetos derivados de la clase System.Array. Por lo tanto, y esto
es muy importante, cuando declaramos un array en C# este aún no se habrá
creado, es decir, no se habrá reservado aún memoria para él. En consecuencia,
los arrays de C# son todos dinámicos, y antes de poder usarlos habrá que
instanciarlos, como si fuera cualquier otro objeto. Veamos un breve ejemplo de lo
que quiero decir:

string[] nombres; // Declaración del array


nombres = new string[3]; // Instanciación del array

65 Juan González - Ryan León – Estiven Peña


Origen, evolución y características
técnicas del lenguaje de programación C#
 

En efecto, tal como podéis apreciar, el array nombres será utilizable únicamente a
partir de su instanciación. En este ejemplo, el número 3 que está dentro de los
corchetes indica el número total de elementos de que constará el array. No os
equivoquéis, puesto que todos los arrays de C# están basados en cero, esto es, el
primer elemento del array es cero. Por lo tanto, en este caso, el último elemento
sería 2 y no 3, ya que son tres los elementos que lo componen (0, 1 y 2). Veamos
un ejemplo algo más completo y después lo comentamos:

 
using System;
 
namespace Arrays
{
    class ArraysApp
    {
        static void Main()
        {
            string[] nombres; // Declaración del array
            ushort num=0;
 
            do
            {
                try
                {
                    Console.Write("¿Cuántos nombres vas a introducir? ");
                    num=UInt16.Parse(Console.ReadLine());
                }
66 Juan González - Ryan León – Estiven Peña
Origen, evolución y características
técnicas del lenguaje de programación C#
                catch
                {
                    continue;
                }
            } while (num==0);
 
            nombres=new string[num]; // Instanciación del array
 
            for (int i=0; i<num; i++)
            {
                Console.Write("Escribe el nombre para elemento {0}: ", i);
                nombres[i]=Console.ReadLine();
            }
 
            Console.WriteLine("Introducidos los {0} nombres", num);
            Console.WriteLine("Pulsa INTRO para listarlos");
 
            string a=Console.ReadLine();
 
            for (int i=0; i<num; i++)
            {
                Console.WriteLine("Elemento {0}: {1}", i, nombres[i]);
            }
 
            a=Console.ReadLine();
        }
    }
}

67 Juan González - Ryan León – Estiven Peña


Origen, evolución y características
técnicas del lenguaje de programación C#
 

Veamos ahora la salida en la consola (en rojo, como siempre, lo que se ha escrito
durante la ejecución del programa):

¿Cuántos nombres vas a introducir? 3


Escribe el nombre para el elemento 0: Juanito
Escribe el nombre para el elemento 1: Jaimito
Escribe el nombre para el elemento 2: Joselito
Introducidos los 3 nombres
Pulsa INTRO para listarlos
Elemento 0: Juanito
Elemento 1: Jaimito
Elemento 2: Joselito
 
En este pequeño programa hemos declarado un array y lo hemos instanciado
después de haber preguntado al usuario cuántos elementos iba a tener. Como
veis, hemos utilizado un bucle for para recoger todos los valores que hay que
meter en el array. Quiero que prestéis especial atención a cómo hemos
introducido los valores en el array: en la línea "nombres[i] = Console.ReadLine()"
lo que hacemos es que al elemento "i" del array le asignamos lo que devuelva el
método ReadLine. Como "i" tomará valores entre 0 y el número total de elementos
menos uno rellenaremos el array completo (fijaos en la condición del bucle, que es
i<num, es decir, que si i es igual a num el bucle ya no se itera). Después tenemos
otro bucle for para recorrer todo el array y escribir sus valores en la consola. En
definitiva, para acceder a un elemento del array se usa la sintaxis "array[índice]".

Un array también puede inicializarse en la propia declaración, bien instanciándolo


(como cualquier otro objeto) o bien asignándole los valores directamente. Vamos a
reescribir el ejemplo anterior instanciando el array en la declaración del mismo:

68 Juan González - Ryan León – Estiven Peña


Origen, evolución y características
técnicas del lenguaje de programación C#
 

using System;
 
namespace Arrays2
{
    class Arrays2App
    {
        static void Main()
        {
            ushort num=3;
 
            do
            {
                try
                {
                    Console.Write("¿Cuántos nombres vas a introducir? ");
                    num=UInt16.Parse(Console.ReadLine());
                }
                catch
                {
                    continue;
                }
            } while (num==0);
 
            string[] nombres=new string[num]; // Declaración e instanciación del array
 
            for (int i=0; i<num; i++)

69 Juan González - Ryan León – Estiven Peña


Origen, evolución y características
técnicas del lenguaje de programación C#
            {
                Console.Write("Escribe el nombre para elemento {0}: ", i);
                nombres[i]=Console.ReadLine();
            }
 
            Console.WriteLine("Introducidos los {0} nombres", num);
            Console.WriteLine("Pulsa INTRO para listarlos");
 
            string a=Console.ReadLine();
 
            for (int i=0; i<num; i++)
            {
                Console.WriteLine("Elemento {0}: {1}", i, nombres[i]);
            }
 
            a=Console.ReadLine();
        }
    }
}
 
Bien, ahora, como puedes observar, el array ha sido instanciado en la misma línea
en la que fue declarado. El funcionamiento de este ejemplo, por lo tanto, sería el
mismo que el del ejemplo anterior. Veamos ahora otro ejemplo de inicialización del
array asignándole los valores en la declaración:

 
using System;
 
namespace Arrays3

70 Juan González - Ryan León – Estiven Peña


Origen, evolución y características
técnicas del lenguaje de programación C#
{
    class Arrays3App
    {
        static void Main()
        {
            // Declaración e inicialización del array
            string[] nombres={"Juanito", "Jaimito", "Joselito"};
 
            for (int i=0; i<nombres.Length; i++)
            {
                Console.WriteLine("Elemento {0}: {1}", i, nombres[i]);
            }
 
            string a=Console.ReadLine();
        }
    }
}
 
En este caso, el array nombres ha sido inicializado en la propia declaración del
mismo, asignándole los tres valores que va a contener. Como ves, dichos valores
están entre llaves y separados por comas. Las comillas son necesarias en este
caso, ya que el array es de tipo string. ¿Que dónde está la instanciación del array?
Bueno, cuando hacemos esto, la instanciación la hace por debajo el compilador,
es decir, de forma implícita. Presta atención también a la condición del bucle:
ahora hemos usado la propiedad Length del array nombres en lugar de una
variable. En efecto, esta propiedad nos devuelve el número de elementos de un
array. Por lo tanto, la salida en consola de este programa sería esta:

 
Elemento 0: Juanito
71 Juan González - Ryan León – Estiven Peña
Origen, evolución y características
técnicas del lenguaje de programación C#
Elemento 1: Jaimito
Elemento 2: Joselito
 
Por otro lado, el hecho de que un array haya sido inicializado no quiere decir que
sea inamovible. Si un array que ya contiene datos se vuelve a instanciar, el array
volverá a estar vacío, y obtendrá las dimensiones de la nueva instanciación.

Bien, todos estos arrays que hemos explicado hasta el momento son arrays
unidimensionales, es decir, que tienen una sola dimensión (un solo índice). Sin
embargo esto no soluciona aún todas las necesidades del programador.
Pongamos, por ejemplo, que queremos almacenar las combinaciones de las ocho
columnas de una quiniela de fútbol en un array.¿Cómo lo hacemos? Pues bien, el
mejor modo es utilizar un array multidimensional.

72 Juan González - Ryan León – Estiven Peña


Origen, evolución y características
técnicas del lenguaje de programación C#

2.14. Arreglos multidimensionales


Los arrays multidimensionales son aquellos que constan de dos o más
dimensiones, es decir, que cada elemento del array viene definido por dos o más
índices. Vamos a echar un vistazo a la declaración de un array multidimensional
(en este caso, será tridiensional, es decir, con tres dimensiones):

 
tipo[,,] variable;
 
Como ves, hay dos comas dentro de los corchetes, lo cual indica  que el array es
tridimensional, puesto que los tres índices del mismo se separan uno de otro por
comas. Veamos un pequeño ejemplo que lo clarifique un poco más:

 
string[,] alumnos = new string[2,4];
 
Este array es bidimensional y serviría para almacenar una lista de alumnos por
aula, esto es, tenemos dos aulas (el primer índice del array es 2) y cuatro alumnos
en cada una (el segundo índice es 4). Veamos un poco de código y una tabla para
que os hagáis una idea de cómo se almacena esto:

 
alumnos[0,0]="Lolo";
alumnos[0,1]="Mario";
alumnos[0,2]="Juan";
alumnos[0,3]="Pepe";
alumnos[1,0]="Lola";
alumnos[1,1]="María";

73 Juan González - Ryan León – Estiven Peña


Origen, evolución y características
técnicas del lenguaje de programación C#
alumnos[1,2]="Juana";
alumnos[1,3]="Pepa";
 
Esto sería como almacenar los datos en esta tabla:

   AULA 0 AULA 1
NOMBRE 0 Lolo Lola
NOMBRE 1 Mario María
NOMBRE 2 Juan Juana
NOMBRE 3 Pepe Pepa
 
¿Que quieres saber por qué he separado a los chicos de las chicas? Bueno, no es
que sea un retrógrado, es para que se vea mejor todo esto. Mira que sois
detallistas... Bueno, creo que va quedando bastante claro. ¿Y cómo recorremos un
array multidimensional? Pues con bucles anidados. Vamos ya con un ejemplo más
completito de todo esto. Este pequeño programa pregunta al usuario por el
número de columnas que quiere generar de una quiniela de fútbol, y después las
rellena al azar y las muestra en pantalla:

 
using System;
 
namespace Quinielas
{
    class QuinielasApp
    {
        static void Main()
        {
            const char local='1';
            const char empate='X';
            const char visitante='2';
74 Juan González - Ryan León – Estiven Peña
Origen, evolución y características
técnicas del lenguaje de programación C#
            const byte numFilas=14;
            byte numColumnas=0;
            char[,] quiniela;
            byte azar;
            Random rnd=new Random(unchecked((int) DateTime.Now.Ticks));
            
            do
            {
                try
                {
                    Console.WriteLine("Mínimo una columna y máximo ocho");
                    Console.Write("¿Cuántas columnas quieres generar? ");
                    numColumnas=Byte.Parse(Console.ReadLine());
                }
                catch
                {
                    continue;
                }
            } while (numColumnas<1 || numColumnas>8);
 
            quiniela=new char[numColumnas, numFilas];
 
            for (byte i=0; i<numColumnas; i++)
            {
                for (byte j=0; j<numFilas; j++)
                {
                    azar=(byte) (rnd.NextDouble()*3D);
                    switch (azar)

75 Juan González - Ryan León – Estiven Peña


Origen, evolución y características
técnicas del lenguaje de programación C#
                    {
                        case 0:
                            quiniela[i,j]=local;
                            break;
                        case 1:
                            quiniela[i,j]=empate;
                            break;
                        case 2:
                            quiniela[i,j]=visitante;
                            break;
                    }
                }
            }
 
            Console.WriteLine("Quiniela generada. Pulsa INTRO para verla");
            string a=Console.ReadLine();
 
            for (byte i=0; i<numColumnas; i++)
            {
                Console.Write("Columna {0}: ", i+1);
                for (byte j=0; j<numFilas; j++)
                {
                    Console.Write("{0} ", quiniela[i,j]);
                }
                Console.WriteLine();
                Console.WriteLine();
            }
 

76 Juan González - Ryan León – Estiven Peña


Origen, evolución y características
técnicas del lenguaje de programación C#
            a=Console.ReadLine();
        }
    }
}
 
Como veis, esto se va poniendo cada vez más interesante. De este programa,
aparte de la clase Random, hemos visto todo excepto los bloques try y catch, de
modo que si hay algo que no entiendes te recomiendo que revises las entregas
anteriores. La clase Random es para generar números aleatorios (al azar). En la
instanciación de dicha clase hemos puesto algo que puede resultarte algo
confuso. Es esta línea:

 
Random rnd=new Random(unchecked((int) DateTime.Now.Ticks));
 
Bien, el constructor de esta clase tiene dos sobrecargas: una de ellas es sin
argumentos, y la otra acepta un argumento de tipo int, que es la que hemos
usado. ¿Por qué? Porque de lo contrario siempre generaría los mismos números
en cada ejecución del programa, lo cual no sería muy útil en este caso. Como
necesitamos que se generen números distintos tenemos que pasarle números
diferentes en el argumento int del constructor de la clase Random, y el modo más
eficaz de conseguirlo es hacer que ese número dependa del tiempo que lleve
encendido el ordenador. Por otro lado, el número lo generamos al ejecutar el
método NextDouble, el cual nos retorna un número mayor o igual a 0 y menor que
esta es la línea:

 
azar=(byte) (rnd.NextDouble()*3D);
 

77 Juan González - Ryan León – Estiven Peña


Origen, evolución y características
técnicas del lenguaje de programación C#

¿Por qué lo hemos multiplicado por 3D? Pues bien, como queremos números
enteros entre 0 y 2 (o sea, 0, 1 o 2) bastará con multiplicar este número (recuerda
que está entre cero y uno) por 3. ¿Y la D? Ahora voy, hombre. ¿Os acordáis de
los sufijos en los literales, para indicar si se debía considerar si el número era de
un tipo o de otro? Pues aquí está la explicación. Dado que el método NextDouble
retorna un valor double, tenemos que multiplicarlo por otro valor double. Por eso le
ponemos el sufijo "D" al número tres. Después todo ese resultado se convierte a
byte y se asigna a la variable azar, que es la que se comprueba en el switch para
asignar el carácter necesario según su valor a cada elemento del array.

 Por lo demás creo que a estas alturas no debería tener que explicaros gran cosa:
tenemos un par de bucles anidados para asignar los valores al array y después
otros dos bucles anidados para recorrer dicho array y mostrar su contenido en la
consola.

Otra cuestión importante en la que quiero que te fijes es en que ya estoy


empezando a dejar de usar "literales y números mágicos", usando constantes en
su lugar. Efectivamente, podría haberme ahorrado las cuatro constantes: local,
empate, visitante y numFilas, poniendo sus valores directamente en el código,
algo así:

 ...
            for (byte i=0; i<numColumnas; i++)
            {
                for (byte j=0; j<14; j++)
                {
                    azar=(byte) (rnd.NextDouble()*3D);
                    switch (azar)
                    {

78 Juan González - Ryan León – Estiven Peña


Origen, evolución y características
técnicas del lenguaje de programación C#
                        case 0:
                            quiniela[i,j]='1';
                            break;
                        case 1:
                            quiniela[i,j]='X';
                            break;
                        case 2:
                            quiniela[i,j]='2';
                            break;
                    }
                }
            }
...
 
En efecto, funcionaría exactamente igual, pero ¿qué ocurriría si otra persona que
no sabe qué es una quiniela, o por qué tiene que ser el número 14, o qué
significan el 1, la X o el 2? Pues que el código sería menos claro. Las constantes,
sin embargo, hacen la lectura del código más fácil. Por otro lado, si algún día
cambiaran los signos, por ejemplo, si hubiese que poner una "a" en lugar del "1",
una "b" en lugar de la "x" y una "c" en lugar del "2" y no hubiésemos usado
constantes habría que buscar todos estos literales por todo el código y sustituirlos
uno por uno, mientras que usando constantes (que están declaradas al principio)
basta con modificar sus valores, haciendo así el cambio efectivo ya para todo el
programa. Así que ya lo sabéis: a partir de ahora vamos a evitar en lo posible los
"literales y los números mágicos".

Para terminar con esto, el número de dimensiones de un array se llama rango.


Para conocer el rango de un array mediante código basta con invocar la propiedad
Rank del mismo (heredada de la clase System.Array). Veamos un ejemplo de
esto:

79 Juan González - Ryan León – Estiven Peña


Origen, evolución y características
técnicas del lenguaje de programación C#
 
using System;
 
namespace Rangos
{
    class RangosApp
    {
        static void Main()
        {
            int[] array1=new int[2];
            int[,] array2=new int[2,2];
            int[,,] array3=new int[2,2,2];
            int[,,,] array4=new int[2,2,2,2];
 
            Console.WriteLine("Rango de array1: {0}", array1.Rank);
            Console.WriteLine("Rango de array2: {0}", array2.Rank);
            Console.WriteLine("Rango de array3: {0}", array3.Rank);
            Console.WriteLine("Rango de array4: {0}", array4.Rank);
 
            string a=Console.ReadLine();
        }
    }
}
 
La salida en la consola de todo esto sería la siguiente:
 
Rango de array1: 1
Rango de array2: 2

80 Juan González - Ryan León – Estiven Peña


Origen, evolución y características
técnicas del lenguaje de programación C#
Rango de array3: 3
Rango de array4: 4

2.15. Arraylist

Los Arraylist y sus caracteristicas:


Los arreglos convencionales tienen un tamaño fijo que no se puede modificar
conforme se está ejecutando un Programa.Los objetos ArrayList imitan la
funcionalidad de los arreglos convencionales y proporcionan la capacidad de
modificar el tamaño del arreglo de forma dinámica a través de sus métodos

Un ArrayList puede almacenar Objetos de cualquier tipo.

Se require agregar el espacio de nombres CollecAons con la siguiente


Línea: using System.Collections

Se crea el objeto de
Tipo ArrayList Así:
ListaNaves = new ArrayList();
Con Esto el constructor default crea un ArrayList vacío.

Métodos y propiedades de la clase ArrayList

Para agregar un objeto al arrayList se usa el método Add , de esta


forma:

81 Juan González - Ryan León – Estiven Peña


Origen, evolución y características
técnicas del lenguaje de programación C#
Nave objeto = new Nave (.....);
listaNaves.
Add(objeto);

El método Add agrega los objetos en el ArrayList en el orden en el que se van


agregando y el tamaño del ArrayList se va ajustando.

Métodos y Propiedades de la clase ArrayList

Count: es una propiedad de solo lectura que optiene el número de elementos que
cntiene el ArrayList.

Clear es un método que elimina todos los elementos del ArrayList.

RemoveAt(indice) es un método que elimina el objeto que se encuentra en el


índice que se especifica.

Se puede hacer referencia a los elementos de un ArrayList usando


[ ] de la misma forma que se usan para un arreglo normal.

82 Juan González - Ryan León – Estiven Peña


Origen, evolución y características
técnicas del lenguaje de programación C#

2.16. HashMap
Un HashMap es la implementación de la interface Map, esta interface es un tipo
de Collection  que almacena datos asociando una llave a un valor, esta interface
sirve para muchas cosas y tiene ciertas caracteristicas que la definen, por ejemplo,
no permite key duplicados, cada key tiene que estar asociado a un valor como
máximo, si agregas un key que ya existe sobrescribe el valor del key anterior, solo
permite Object types lo que quiere decir que no puedes poner un valor primitivo.

using System.Collections.Generic;
void HashMaps()
{
Dictionary<string, int?> map = new Dictionary<string, int?>();
string s = "test";
map[s] = 1;
int i = map[s].Value;
i = map.Count;
bool b = map.Count == 0;
map.Remove(s);
}

83 Juan González - Ryan León – Estiven Peña


Origen, evolución y características
técnicas del lenguaje de programación C#

2.17. Genéricos
Los genéricos, y más concretamente en este post los tipos genéricos, son un
mecanismo de C# que nos ayuda a maximizar la reutilización de código. La
reutilización de código se logra a través de el uso de plantillas (templates) de
código en las cuales se insertan marcadores (placeholders) que representarán los
tipos de dato que usaremos en nuestra plantilla.

Sintaxis

La declaración de tipos genéricos se realiza casi como cualquier otro tipo, con la
diferencia de que tenemos que declarar los placeholders entre signos < y >, por
ejemplo:

public class Box<T>

En la cual le estamos indicando que usaremos un marcador llamado T. Que se lee


como “Box de T”. Luego entonces dentro de la declaración de la clase podemos
reutilizar el marcador T tantas veces como queramos:

public T Content { get; private set; }

public Box(T content)


{
Content = content;

84 Juan González - Ryan León – Estiven Peña


Origen, evolución y características
técnicas del lenguaje de programación C#
}

Para hacer uso de un tipo genérico la sintaxis es más o menos igual a cualquier
tipo por referencia: debemos usar el operador new, el constructor de la clase e
indicarle dentro de < y > los tipos con los que queremos que se reemplaze el
marcador.

var cajaDeEntero = new Box<int>(5);


var cajaDeString = new Box<string>("Hola mundo");

Console.WriteLine(cajaDeEntero.Content); // 5
Console.WriteLine(cajaDeString.Content); // Hola mundo

También podemos anidar declaraciones en los tipos genéricos:


var cajaDeCajas = new Box<Box<string>>(cajaDeString);
Console.WriteLine(cajaDeCajas); // [Box: Content=[Box: Content=Hola mundo]]

No hay “límite” en cuanto al nombre o cantidad de tipos que podemos usar. Usar
los genéricos permiten dos cosas: Incrementar la reutilización de código
manteniendo el tipado fuerte y reducir el impacto al desempeño en nuestras apps
al evitar el boxing y unboxing, de ahí la importancia de su existencia.

85 Juan González - Ryan León – Estiven Peña


Origen, evolución y características
técnicas del lenguaje de programación C#

2.18. Linq
LINQ o Language Integrated Query son un conjunto herramientas de Microsoft
para realizar todo tipo de consultas a distintas fuentes de datos: objetos, xmls,
bases de datos, etc... Para ello, usa un tipo de funciones propias, que unifica las
operaciones más comunes en todos los entornos, con esto, se consigue un mismo
lenguaje para todo tipo de tareas con datos.

LINQ nace en el Framework 3.5 y pronto coge una gran aceptación entre el mundo
de .net, tanto es asi, que enseguida salen proveedores de terceros, para el uso de
este lenguaje con JSON, CSVs, o inclusos APIs como la de Twitter y Wikipedia.

LINQ en C#
La sintaxis es parecida a la existente en SQL, pero con la ventaja de que tenemos
la potencia de .net y visual studio a la hora de codificar. Ahora vamos a ver un
sencillo ejemplo, con una consulta linq en c# para objetos (LINQ to objetcs):

var lista = from c in coleccion


where c.propiedad1 == true
select c;

Como podemos ver, accedemos a una colección y filtramos todos los elementos
que cumplan que la propiedad 1 sea verdadera. Del resultado de esta consulta,
podemos sacar un listado de elementos con ToList(), el número de ellos con un
count(), extraer los datos a un array, entre otros.

86 Juan González - Ryan León – Estiven Peña


Origen, evolución y características
técnicas del lenguaje de programación C#

Capítulo 3: Glosario de términos o palabras clave de C#

Las palabras claves de este lenguaje de programacion c sharp son los siguientes
nombres no son válidos como identificadores ya que tienen un significado
especial en el lenguaje: abstract, as, base, bool, break, byte, case

, catch, char, checked, class, const, continue, decimal, default, delegate, do,

double, else, enum, event, explicit, extern, false, finally, fixed, float, for, foreach,
goto, if, implicit, in, int, interface, internal, lock, is, long, namespace, new, null,
object, operator, out, override, params, private, protected, public, readonly, ref,
return, sbyte, sealed, short, sizeof, stackalloc, static, string, struct, switch, this,
throw, true, try, typeof, uint, ulong, unchecked, unsafe, ushort, using, virtual, void,
while.

Aparte de estas palabras reservadas, si en futuras implementaciones del lenguaje


se decidiese incluir nuevas palabras reservadas, Microsoft dice que dichas
palabras habrían de incluir al menos dos símbolos de subrayado consecutivos (_)
Por tanto, para evitar posibles conflictos futuros no se recomienda dar a nuestros
identificadores nombres que contengan dicha secuencia de símbolos.

Aunque directamente no podemos dar estos nombres a nuestros identificadores,


C# proporciona un mecanismo para hacerlo indirectamente y de una forma mucho
más legible que usando secuencias de escape.

87 Juan González - Ryan León – Estiven Peña


Origen, evolución y características
técnicas del lenguaje de programación C#
Este mecanismo consiste en usar el carácter @ para prefijar el nombre
coincidente con el de una palabra reservada que queramos dar a nuestra variable.
Por ejemplo, el siguiente código es válido:

class @class
{
static void @static(bool @bool)
{
if (@bool)
Console.WriteLine("cierto");
else
Console.WriteLine("falso");
}
}
Lo que se ha hecho en el código anterior ha sido usar @ para declarar una clase
de nombre class con un método de nombre static que toma un parámetro de
nombre bool, aún cuando todos estos nombres son palabras reservadas en C#.

Hay que precisar que aunque el nombre que nosotros es cribamos sea por
ejemplo @class, el nombre con el que el compilador va a tratar internamente al
identificador es solamente class.

De hecho, si desde código escrito en otro lenguaje adaptado a .NET distinto a C#


hacemos referencia a éste identificador y en ese lenguaje su nombre no es una
palabra reservada, el nombre con el que deberemos referenciarlo es

88 Juan González - Ryan León – Estiven Peña


Origen, evolución y características
técnicas del lenguaje de programación C#
Class , y no @class (si también fuese en ese lenguaje palabra reservada habría
que referenciarlo con el mecanismo que el lenguaje incluyese para ello, que
quizás también podría consistir en usar @ como en C#).

En realidad, el uso de @ no se tiene porqué limitar a preceder palabras


reservadas en C#, sino que podemos preceder cualquier nombre con él. Sin
embargo, hacer esto no se recomienda, pues es considerado como un mal hábito
de programación y puede provocar errores muy sutiles como el que muestra el
siguiente ejemplo:

class A
{
int a; // (1)
int @a; // (2)
public static void Main()
{}
}
Si intentamos compilar este código se producirá un error que nos informará de que
el campo de nombre a ha sido declarado múltiples veces en la clase A.

Esto se debe a que como @ no forma parte en realidad del nombre del
identificador al que precede, las declaraciones marcadas con comentarios como
(1) y (2) son equivalentes.

Hay que señalar por último una cosa respecto al carácter @: sólo puede preceder
al nombre de un identificador, pero no puede estar contenido dentro del mismo. Es
decir, identificadores como i5322@fie.us.es no son válidos.

89 Juan González - Ryan León – Estiven Peña


Origen, evolución y características
técnicas del lenguaje de programación C#

Capítulo 4: Principales ventajas que presenta el uso C#


en comparación con otros lenguajes

Ventajas frente a C y C++


 Compila a código intermedio (CIL) independiente del lenguaje en que haya
sido escrita la aplicación e independiente de la máquina donde vaya a
ejecutarse

 Recolección de basura automática

 Eliminación del uso punteros, en C# no se necesitan

 No hay que preocuparse por archivos de cabecera ".h"

 No importa el orden en que hayan sido definidas las clases ni las funciones

 No hay necesidad de declarar funciones y clases antes de definirlas

 No existen las dependencias circulares

 Soporta definición de clases dentro de otras

 No existen funciones, ni variables globales, todo pertenece a una clase


90 Juan González - Ryan León – Estiven Peña
Origen, evolución y características
técnicas del lenguaje de programación C#
 Todos los valores son inicializados antes de ser usados (automáticamente
se inicializan al valor estandarizado, o manualmente se pueden inicializar
desde constructores estáticos)

 No se pueden utilizar valores no booleanos (enteros, coma flotante...) para


condicionales. Es mucho más limpio y menos propenso a errores

 Puede ejecutarse en una sandbox restringida

Ventajas frente a Java


 El rendimiento es, por lo general, mucho mejor

 CIL (el lenguaje intermedio de .NET) está estandarizado, mientras que los
bytecodes de java no lo están

 Soporta bastantes más tipos primitivos (value types), incluyendo tipos


numéricos sin signo

 Indizadores que permiten acceder a cualquier objeto como si se tratase de


un array

 Compilación condicional

 Aplicaciones multi-hilo simplificadas

 Soporta la sobrecarga de operadores, que aunque pueden complicar el


desarrollo son opcionales y algunas veces muy útiles

 Permite el uso (limitado) de punteros cuando realmente se necesiten, como


al acceder a librerías nativas que no se ejecuten sobre la máquina virtual

Ventajas frente a PHP


91 Juan González - Ryan León – Estiven Peña
Origen, evolución y características
técnicas del lenguaje de programación C#
 PHP es interpretado y le aplican las reglas arriba mencionadas, además. no
mencionaremos las clásicas relacionadas con la sintaxis horrible, el mal
soporte para concurrencia, etc. , porque dicen las malas lenguas que php7
es súper poderoso y que es muy distinto a su antiguo y feo hermanito
menor php5.

Ventajas frente a Node


Node y cualquiera otro de los lenguajes de tipos dinámicos, C# es de tipado
estático lo que en mi opinión es una ventaja en desarrollos grandes, el compilador
detectara muchos de tus errores, el debugeo será más sencillo , y una larga lista
de ventajas de los lenguajes de tipos estáticos , además es más bonito que JS.

Ventajas frente Elixir / Haskell


El código que produce .net tiene mejor performance, existen más librerías , más
trabajos , mas fuentes de información.

Ventajas frente a Visual Basic


La ventaja de C# sobre .NET es que muchas cosas salen primero para C# y luego
para VB. Por ejemplo, el proyecto Mono de .Net para Linux, funciona en C# (creo
que ahora ya le están agregando VB.Net).

Luego, no hay ninguna ventaja ni desventaja. Ambos compilan a un mismo código


intermedio (MSIL) que es interpretado por el JIT. Hay páginas en las que te
demuestran que sendos códigos C# y VB.NET compilan al mismo código MSIL,
nota que para un programador C++ es más fácil escribir código en C# que en VB.
92 Juan González - Ryan León – Estiven Peña
Origen, evolución y características
técnicas del lenguaje de programación C#
Es una cuestión de costumbre, nada más. Vos estás acostumbrado al "End If",
ellos a la "}".

Conclusión

Al concluir este trabajo nos damos cuenta que nuestro proceso de formación está
basado en un continuo cambio, de conocimiento para el mejoramiento de nuestra
labores (que aplicamos en base a un estudio que se está adquiriendo para mejorar
día a día) y con el objetivo de llegar a ser un buen licenciado en informática, con
las competencias que la materia nos ha suministrado y haciéndonos saber lo
importante que son los lenguajes de programación, ya que a la hora de desarrollar
aplicaciones o programas siempre será tema de controversia, ya que al principio
nunca se sabe por cual lenguaje declinarse, pero todo dependerá del gusto de la
persona con el desarrollo del tiempo y estudiando todos los lenguajes
competentes como ya conocemos unos de los mejores hoy en día del cual se está
93 Juan González - Ryan León – Estiven Peña
Origen, evolución y características
técnicas del lenguaje de programación C#
tratando en este tema que es el C#, es un lenguaje de programación orientado a
objetos desarrollado y estandarizado por Microsoft como parte de su plataforma
.NET.

Bibliografía
https://www.campusmvp.es/recursos/post/historia-del-lenguaje-c-sharp-pasado-
presente-y-evolucion.aspx
https://docs.microsoft.com/es-es/dotnet/csharp/whats-new/csharp-version-history
https://docs.microsoft.com/es-es/dotnet/csharp/programming-guide/classes-and-
structs/using-structs
https://docs.microsoft.com/es-es/dotnet/csharp/programming-guide/
http://programacion1abundiz.blogspot.com/2009/09/generalidades-y-
caracteristicas-c_08.html
http://di002.edv.uniovi.es/~benja/cs/presentaciones/2-
CsCaracteristicasGenerales.pdf
http://www.cartagena99.com/recursos/alumnos/apuntes/Practica
%202.%20Introduccion%20a%20la%20programacion%20visual.pdf
https://prezi.com/svgcz8hk7js5/modo-consola-y-grafico-en-c/
https://es.wikipedia.org/wiki/C_Sharp
https://prezi.com/peupc5qiedn7/entorno-de-visual-c/
https://msdn.microsoft.com/es-ar/library/yht2cx7b(v=vs.80).aspx
https://geeks.ms/etomas/2010/07/14/c-bsico-que-es-la-herencia/
https://informaticapc.com/poo/clases-abstractas.php
https://geeks.ms/etomas/2010/07/07/c-bsico-interfaces/

94 Juan González - Ryan León – Estiven Peña


Origen, evolución y características
técnicas del lenguaje de programación C#
https://docs.microsoft.com/es-es/dotnet/csharp/programming-
guide/exceptions/using-exceptions
https://docs.microsoft.com/es-es/dotnet/csharp/language-reference/keywords/while
http://www.mundonet.es/arrays-arrays-multidimensionales-arrays-de-arrays.html?
Pg=Entrega11.htm
http://proyectofinalcisp.weebly.com/uploads/2/2/8/7/22873198/arraylist.pdf
https://thatcsharpguy.com/post/genericos-c-sharp-clases/
http://www.tuprogramacion.com/glosario/que-es-linq/
http://dis.um.es/~bmoros/privado/bibliografia/LibroCsharp.pdf
http://www.Google.com
http://www.Aprende.org
http://www.urriellu.net
http://www.valeriamenendez.blogspot.com/
http://www.es.wikipedia.org
http://www.zkanji.wordpress.com
El lenguaje de programación C# Tema 4: Aspectos léxicos, José Antonio González
Seco

Anexos

95 Juan González - Ryan León – Estiven Peña


Origen, evolución y características
técnicas del lenguaje de programación C#

96 Juan González - Ryan León – Estiven Peña

También podría gustarte