Documentos de Académico
Documentos de Profesional
Documentos de Cultura
IFTS18 - Introduccion A C# v1.0 PDF
IFTS18 - Introduccion A C# v1.0 PDF
Introducción a C#
Programación Aplicada
Autor:
Ing. Gabriel Esquivel
Año:
2018
IFTS18 Introducción a C# 2018
Tabla de contenido
Introducción .................................................................................................................................. 5
Sistema Operativo ......................................................................................................................... 5
.Net Framework ............................................................................................................................ 8
Lenguaje Intermedio (IL) .................................................................................................................... 9
Task Manager - Process Explorer ..................................................................................................... 11
Tiempos de Desarrollo de una Aplicación ................................................................................... 13
Resumen.................................................................................................................................. 13
Concepción del Producto – Especificaciones y Alcance del Proyecto.............................................. 14
Pre/Re Diseño y Análisis: ................................................................................................................. 14
Design Time o Tiempo de Diseño ..................................................................................................... 16
Programming-Editing Time o Tiempo de Programación-Edición: ................................................... 18
Compilación ...................................................................................................................................... 19
Execution & Debugging Time o Tiempo de Ejecución y Depuración .............................................. 20
Quality Test o Verificación de Calidad ............................................................................................. 20
Clasificación de los Lenguajes ..................................................................................................... 21
Código de Maquina ................................................................................................................. 21
Programación de Bajo Nivel .................................................................................................... 21
Programación de Nivel Intermedio ......................................................................................... 22
Programación de Alto Nivel .................................................................................................... 23
Paradigmas de Programación ..................................................................................................... 25
Programación Estructurada u Orientada a Métodos .............................................................. 25
Funciones - Métodos ......................................................................................................................... 26
Programación Orientada a Eventos ........................................................................................ 29
Evento ............................................................................................................................................... 29
Entorno de Desarrollo ................................................................................................................. 31
Editor de Código ...................................................................................................................... 31
Diseñador/Editor de Formularios............................................................................................ 32
Proyectos y Soluciones ..................................................................................................................... 33
Panel Explorador de Soluciones ....................................................................................................... 33
Panel de Propiedades ........................................................................................................................ 34
Examinador de Objetos ..................................................................................................................... 35
Aplicaciones y Formularios.......................................................................................................... 37
Creación de un nuevo Proyecto .............................................................................................. 37
Programación Orientada Objetos ............................................................................................... 40
Concepto de Objeto ................................................................................................................ 40
Miembros de un objeto........................................................................................................... 41
Clases....................................................................................................................................... 41
Sistema Operativo
Es un software complejo, formado por una gran cantidad y variedad de sub aplicaciones y
bibliotecas que se encargan de servir de soporte a las aplicaciones de alto nivel del usuario,
separando a estas de las diferencias entre los distintos hardwares disponibles en el mercado
moderno.
Un esquema simple de lo mencionado es el mostrado:
Figura 1. Capas de un Sistema Operativo
Aplicaciones del
Usuario Capa de
Aplicación
Servicios del Usuario Mayor Nivel de Privilegios
Software
Sistema
Operativo
Hardware
HardWare
Aplicaciones del
Usuario Capa de
Aplicación
Servicios del Usuario
.Net Framework
Software
directo a
Hardware
APIs de Windows Prohibido
HAL
Hardware
HardWare
Como se aprecia en la figura, el sistema operativo aísla al hardware de las aplicaciones del
usuario. Debido a ello, el usuario podrá correr sus programas habituales (Word, Excel, Corel,
etc.) despreocupándose de las sutilezas que a muy bajo nivel suceden.
Este esquema permite entonces que dichas aplicaciones corran prácticamente en cualquier PC
de escritorio o portátil.
La última capa del Sistema Operativo, el HAL (Hardware Abstraction Layer ó Capa de
Abstracción del Hardware en castellano) es la encargada de separar a su vez al núcleo del
sistema, denominado a menudo Kernel, de todas las posibles combinaciones de hardware
halladas en el mercado.
El Kernel es el encargado de las tareas básicas que hacen al funcionamiento del Sistema, tales
como el acceso a disco para la lectura y escritura de archivos, la administración de memoria,
etc.
.Net Framework
Así denominó Microsoft a su conjunto de bibliotecas que, por encima de cualquiera de sus
sistemas operativos Windows, dan soporte a la creación de potentes aplicaciones, servicios,
bibliotecas y páginas webs, entre otros tipos de proyectos.
En el siguiente gráfico se puede ver la estructura de capas del software que corre en una
computadora, y el lugar específico del .Net Framework en éste.
Figura 3. Estructura en capas de una aplicación .Net después de ser compilada
VB .Net C# VC ++ Otros
Código Fuente
.Net Lenguajes
Visual Studio
Aplicaciones
IDE
Compilación
Aplicación IL
Lenguaje
Intermedio
Biblioteca IL
Como apreciará, a partir de una gran variedad de lenguajes, entre los que se destacan C# y
Visual Basic .Net, y con el uso de un software especializado denominado IDE (de Integrated
Development Environment, como el Visual Studio) es posible escribir código fuente, que tras
ser compilado, produce una aplicación y/o bibliotecas, las que basadas en las librerías de alto
nivel sistema, como el .Net Framework en Windows o Mono y DotGNU con Linux y MacOS
(entre otros sistemas operativos), permiten que estos corran o interactúen con el SO.
PLINQ TPL
4.0
LINQ ADO .NET Entity
3.5
FrameWork
3.0
Space
Como podrá apreciar, la estructura en capas que se ha planteado, desarrollando una sobre la
otra, permite crear un juego de bibliotecas realmente muy poderoso y funcional, comenzando
con el Framework 2.0 y llegando hasta el último 4.0.
Las bibliotecas más básicas, como las contenidas en el Framework 2.0 permiten desarrollar
aplicaciones muy potentes, pero con la tecnología disponible en el Windows Presentation
Foundation o WPF, las aplicaciones creadas pueden manifestar y mostrar efectos visuales
deslumbrantes y hasta sorprendentes, sin necesariamente complicar mucho el código fuente
producido.
Dado que los detalles de cada una de estas tecnologías son ampliamente bastos, salvo algunas
excepciones, se deja al lector investigar cada uno de ellos en función de sus propias
necesidades.
Compilación
Visual Studio
Aplicaciones
IDE
Aplicación Win32
Aplicación IL
Lenguaje
Compilación Intermedio
Biblioteca IL
SO Sistema
Windows Operativo
Por supuesto, el microprocesador no corre código IL, y debido a ello, este debe ser
recompilado a código de máquina antes de que la aplicación se ejecute. Dicha aplicación en
código de maquina se mantiene en un cache salvo que una nueva versión o una diferente del
ejecutable se ejecute.
Esta metodología de trabajo es similar a la utilizada previamente por SUN Microsystems con su
lenguaje Java, su código intermedio denominado Java ByteCode, y su Java Virtual Machine.
Resumen
Las diferentes etapas del diseño de una aplicación pueden apreciarse debajo:
Figura 7. Etapas de desarrollo de una aplicación
Desarrollo
Finalizado Pre/Re Diseño -
Relevamiento
Rediseño Parcial
Diseño de
Formularios
Chequeo de
Calidad
Programación
Errores de Errores de
ejecución Compilación
Ejecución y Compilación
Depuración
Como podrá ver, siempre hay ciclos donde se hacen correcciones, pero solo uno es desastroso,
y es aquel en el cual el diseño tiene que ser replanteado casi en su totalidad, produciendo
pérdidas considerables al desarrollo, generalmente en dinero y/o tiempo.
Herencia
Clase Base
Métodos
Miembros
Como apreciará, los tiempos mínimos necesarios e inclusive algunos retrasos inesperados
pueden ser tenidos en cuenta aquí para poder cumplir con los plazos óptimos esperados.
Control
Control
Código
XAML
En la imagen se puede apreciar, tanto la vista diseño, donde gráficamente se ubican los
componentes y controles en el formulario, así como el código XAML (una variante del XML)
asociado a dichos elementos.
El Diseñador Grafico que se encargue de dicho formulario puede ubicar los controles
visualmente manipulando estos con el mouse, o puede directamente escribir en el código
XAML asociado, como si una página WEB se tratase.
Código vinculado al
botón
IntelliSense
Control
Diseño de
Formularios
Vinculación
Lógica
Compilación
Compilar el código es el acto que permite generar el código de máquina a partir del código
fuente.
Este acto lo realiza explícitamente el programador cuando acciona dicha opción de menú, o
implícitamente cuando depura y ejecuta el programa.
Antes, sobre todo en lenguajes intermedios como C y C++, el hecho de compilar un programa
era una etapa importante del desarrollo, ya que, tal como hoy en día, permite detectar errores
en el código fuente, generalmente errores de sintaxis. Afortunadamente, los entornos
modernos como el Visual Studio muchas veces compilan y chequean errores en tiempo de
edición, es decir, mientras el programador va escribiendo el mismo código. Esto es totalmente
cierto en Visual Basic .NET, se hace parcialmente en C#, y casi nada en Visual C++. Los errores
aparecen subrayados como si fuesen errores de ortografía, y también están enumerados en un
panel, el panel de Lista de Errores.
Debido a lo mencionado, la diferencia en productividad del VB .Net respecto a C# puede ser
apreciable, y mucho más aun respecto VC++, ya que no es necesario recompilar el proyecto
para ir detectando los posibles errores.
Debido a lo mencionado, dependiendo del lenguaje que se utilice, el hecho de compilar puede
pasar de ser algo muy importante a algo casi intrascendente.
Código de Maquina
Podemos definir al código de maquina como aquel código que directamente interpreta el
micro procesador-controlador.
Como es de esperar, a tan bajo nivel, el código aparece en binario puro, y por lo tanto es lo
menos amigable a la hora de programar.
Todos los lenguajes de más alto nivel tarde o temprano, antes de ser ejecutados son
traducidos a Código de Maquina, ya que como dijimos el Procesador trabaja exclusivamente
en este lenguaje. El proceso de convertir el código original a Lenguaje de maquina se
denomina habitualmente Compilación.
En el grafico que sigue, un bloque de código de maquina es engullido de alguna forma por el
micro procesador, y luego este se encarga de interpretar y procesar adecuadamente.
Figura 14. Ejecución de código de maquina
001010111001
101101110011
010111011101
011011011001
011010111001
001110111001
001110111001
010101110010
Código de Maquina Micro Procesador
001010111001 Ejecución
101101110011
010111011101
011011011001
011010111001
Código Fuente en C
void main( ){
unsigned char j ; Instrucciones en
while( 1 ) { C/C++
Compilación
for (j = 0 ; j < 8 ; j ++ ) {
P1 = num[j] ;
delay_ms(500) ;
}
}
Micro Procesador
001010111001 Ejecución
101101110011
010111011101
011011011001
011010111001
Código de Maquina
También debemos mencionar que el C/C++ puede utilizarse en aplicaciones de alto nivel, como
por ejemplo formularios y bibliotecas, pero, dado que el lenguaje en si presenta ciertas
asperezas, este resulta menos competitivo para tales desarrollos, y es superado fácilmente en
productividad por los lenguajes de alto nivel.
Código Fuente en C#
Código Intermedio
instance char[] ToCharArray () cil managed
{
Re IL_0000: ldarg.0
Compilación IL_0001: call instance int32 System.String::get_Length()
IL_0006: stloc.0
IL_0007: ldloc.0
IL_0008: newarr System.Char
Micro Procesador
001010111001 Ejecución
101101110011
010111011101
011011011001
011010111001
Código de Maquina
Paradigmas de Programación
Si bien existen varios paradigmas que permiten explicar metodologías o formas típicas de
programación, las siguientes 4 son básicos y permiten explicar fácilmente como hoy en día se
programa profesionalmente.
Programación Estructurada
Programación Orientada a Eventos
Programación Orientada a Objetos
Debug Programming ó Execution Time Programming
Inicio Instrucción 1
ejecución
Instrucción 2
Instrucción 3 Fin
En este caso, se han declarado 3 variables en las dos primeras líneas, y tras calcular el
promedio y almacenarlo en una de dichas variables, se procede a mostrar el resultado por la
salida estándar del sistema.
ejecución
Instrucción
Instrucción 2
Instrucción
Llamada a función 1
Ejecución
Instrucción 4 función 2
Instrucción
Llamada a función 2
ejecución
Instrucción
Instrucción 5
Instrucción
Fin
En el dibujo mostrado, el bloque principal de código llama a 2 funciones, las que retornan la
ejecución al bloque principal una vez que cada una de ellas concluye, y finalmente en la
instrucción 5 el bloque principal de código finaliza su ejecución.
prom =calcularpromedio(Min,Max);
Console.WriteLine("el promedio es : {0}", prom.ToString());
Función 1
{
return (a + b) / 2;
}
Función 2
{
return a * b / 2; Función 2: recibe 2 parámetros
}
Como observará, las funciones a veces reciben parámetros, y otras veces devuelven un
resultado, como en estos dos ejemplos mostrados.
Para encerrar las instrucciones dentro de una función, siempre existe algún tipo de
delimitador, que en el caso de C# (al igual que en C/C++) son las llaves {}.
El resultado de ejecutar dicho código es la siguiente aplicación de consola:
Figura 23. Aplicación de consola, con los resultados de la ejecución
Function 1 Function 3
Código
Principal
Function 4
Function 2
Function 5
Por desgracia, este paradigma tiene sus limitaciones. Una de las principales es el hecho de no
poder darle vida al código, ya que rápidamente se aprecia sus limitaciones, sobre todo si se
necesita una aplicación rica en controles, como los formularios de ventana. Sin embargo, este
paradigma sirve de sustento a los otros, que siendo más potentes, se basan en él.
Function 2
Function 1
Lanzamiento
del Evento
Como podrá apreciar, las funciones 1 y 2 solo se ejecutan si el manejador de eventos las llama,
y esto sucede solo si el evento ocurre, como por ejemplo, cuando el usuario hace clic en un
botón.
A veces se suele decir que la función captura el evento cuando el manejador de Eventos la
llama, ya que si se ignora la presencia de éste en memoria, es como si la función mágicamente
fuese ejecutada tras la aparición del Evento.
Constructor
InitializeComponent();
this.button1.Click += new
System.EventHandler(this.button1_Click);
}
Función 1
{
MessageBox.Show("Hola señor!!");
}
}
Si usted se toma el trabajo de borrar la línea donde se asocia al manejador de eventos, con el
evento y el método, observara que tras presionar el botón nada sucederá, tal demostrando la
funcionalidad del manejador de eventos.
Entorno de Desarrollo
El entorno es una aplicación sobrecargada de controles con distintos fines, que permiten en
forma visual o textual crear bibliotecas de clases y controles, y aplicaciones.
Editor de Código
Debajo podemos apreciarla:
Figura 28. Vista del Editor de Código y sus Tabs (Pestañas)
Panel de Barra de Panel Explorador
Barra de Menús de Soluciones
controles Herramientas
Diseñador/Editor de Formularios
Otra imagen del Entorno de desarrollo aparece a continuación:
Figura 29. Vista del diseñador de formularios
Proyectos y Soluciones
Cada vez que nos proponemos hacer una aplicación o una biblioteca vamos a generar una
Solución y al menos un Proyecto que formará parte de dicha Solución.
Sin embargo, si deseamos por ejemplo que las clases de bajo nivel se encuentren disponibles
para ser utilizadas por otras aplicaciones, seguramente generaremos una Biblioteca .dll que
contenga a dichas clases, por lo tanto en nuestra solución tendremos que generar otro
Proyecto, en éste caso el de una Biblioteca de Clases.
Solución
Proyecto 1
Proyecto principal
Referencias a
Bibliotecas
Archivo de
Formulario XAML
Las Referencias a Bibliotecas permiten acceder a clases fuera de nuestro proyecto, por
ejemplo a la clase UserControl que permite generar un nuevo formulario WPF y se halla en el
namespace System.Windows.Controls dentro de la biblioteca PresentationFramework.dll. Son
una “especie de acceso directo” para acceder al contenido de la .dll especificada.
Panel de Propiedades
El Panel de Propiedades utiliza un ComboBox en modo diseño para seleccionar el objeto que se
desea inspeccionar y/o modificar, y un PropertyGrid que muestra todas las propiedades
visibles1 del objeto seleccionado. Por ejemplo, para el formulario de la Figura 29. tenemos:
Figura 31. Vista del panel de propiedades
ComboBox para
la selección de
Opciones del Formulario o
PropertyGrid Control. Permite
seleccionar otros
objetos
Grupo de
Propiedades
contraído
Propiedades
agrupadas por
categoría
Propiedad
seleccionada
Valor de la
Propiedad
1
Es posible declarar propiedades que no son visibles al Panel de Propiedades
Miembro seleccionado
(la clase en éste caso)
En la declaración de los miembros se podrá ver el Tipo de objeto específico del Miembro, así
como los Parámetros que se le pasan. En el ejemplo de la figura anterior el objeto
seleccionado es Button, y se puede apreciar que es una clase que hereda de ButtonBase, y se
encuentra en System.Windows.Controls.
Aplicaciones y Formularios
Veamos un ejemplo simple de cómo generar una aplicación básica.
Como podrá apreciar, las opciones son varias, desde la elección del lenguaje de programación
hasta la posibilidad de indicar el tipo de proyecto de salida.
Para nuestro ejemplo las opciones son las indicadas en la imagen previa. Tras presionar el
botón Aceptar obtenemos una imagen como el de la Figura 29.
Los archivos generados tras éste primer paso son los siguientes:
Figura 34. Contenido del directorio donde se aloja nuestro proyecto
Encapsulado método
público
método 1 método 2
método
privado
Variable
Local
propiedad
Miembros de un objeto
A éstas características que poseen los objetos se las denominan miembros y entre ellas
podemos mencionar:
Variables Miembro – en POO se las denomina campos
Las Propiedades
Los Métodos – antes se llamaban funciones
Los Eventos
La declaración de un objeto mediante código se hace con la palabra reservada class (clase), y
será analizada a continuación.
Clases
Una clase es el código de declaración de un objeto, mientras que un objeto es una instancia de
una clase.
Es como hablar de los planos de un barco (la clase) y del propio barco (el objeto o instancia de
la clase). Crear más instancias de una clase es como construir otros barcos idénticos, solo que
cada barco luego podrá tener sus propias características distintivas, como el color de la
cubierta, nombre, tripulación, etc.
Heredar de una clase es como diseñar un nuevo barco utilizando como base los planos del
primero. Debido a ello habrá seguramente muchas similitudes entre ambos.
Las clases se pueden declarar de la forma que aparece debajo:
Formas de Declaración Descripción
public class sprite
{
Ésta es la forma usual de declarar una clase básica. Los
protected Color color; miembros de la clase se pueden escribir en cualquier
protected float rotation; orden dentro de la sentencia mostrada, como por
⋮ ejemplo el color y la rotación del sprite.
}
Herencia
Una de las herramientas más potentes de .Net y la POO es el uso de la herencia. Mediante ésta
es posible generar objetos que posean todos o casi todos los miembros de otros (elegidos a
voluntad por el diseñador) que sirven de base para la herencia.
Obviamente también es posible ahorrar y optimizar mucho el código mediante éste
mecanismo, ya que clases que mantengan cierta similitud pueden heredar de una única clase
base que implemente el código común.
2
El uso de public o internal en una clase, no está prohibido en absoluto, pero sin embargo está mal visto,
ya que pone en peligro la integridad de los datos del objeto.
También se puede apreciar que DestruibleSprite hereda de sprite, y tanto Alien, boss y Player
heredan indirectamente de éste último, ya que todos son plausibles de ser destruidos. En otras
palabras, la lógica de los dibujos se encuentra en sprite, y la de la destrucción de un dibujo en
DestruibleSprite.
Un ejemplo simple de código se muestra debajo:
Formas de Declaración Descripción
public class Cuando se utiliza la herencia se apela a la forma
DestruibleSprite:sprite
mostrada. Los : indican que la clase
{
⋮ DestruibleSprite hereda de la clase escrita a la
} derecha, en éste caso de sprite
Interfaces
Dado que la herencia multiple no existe en .Net y C#, una alternativa menos poderosa es
utilizar la implementación de interfaces, como a continuación se muestra:
Declaración Descripción
public interface IDestruible La declaración es similar a la declaración de una clase,
{ solo que no está permitido indicar el nivel de
int Health { get; set; }
} accesibilidad de sus miembros…
En esencia, la Interfaz permite indicar de antemano al menos que miembros estarán
disponibles en las clases que implementen dicha interfaz. Por ejemplo, debajo la clase
DestruibleSprite posee también3 el campo Health:
3
De hecho, la clase está obligada a contener dicho miembro, por eso se suele hablar de que una interfaz
es como un contrato, en el sentido de que obliga a la clase a poseer sus miembros…
Si la clase implementa más de una Interface entonces se deberá separar por comas tantas
veces como Interfaces implemente.
El Constructor
Se trata de un método que se debe correr antes de utilizar al objeto, ya que éste permite que
se cree e inicialice dicho objeto.
La idea es que en éste método se inicializan cada una de las variables miembro. Por ejemplo:
Formas de Declaración Descripción
public class sprite
{ En éste caso el objeto sprite posee
protected Vector2 scale, origin, velocity; varias variables globales, las que se
protected Color color; inicializan dentro del constructor.
public sprite() Todas son importantes, como scale
{ para el factor de escala utilizado al
scale = new Vector2(1.0f); dibujar el sprite, o color, que
origin = new Vector2();
color = Color.White; permite cambiar el color de todo el
} objeto al dibujarlo, etc.
}
public bullet(sprite owner, Vector2? velocity = null, int energy = 2): base()
{
Posicion = owner.Posicion;
if (velocity != null)
this.velocity = (Vector2)velocity;
else
this.velocity = new Vector2(0, -10);
scale = new Vector2(2.0f);
Owner = owner;
Energy = energy;
}
}
Descripción
Aquí ampliamos el ejemplo previo.
La primera línea del constructor debe incluirse la llamada al constructor de la clase base, con
los :base(), debido a que el propio sistema nos obliga a llamarlo así.
El segundo parámetro del tipo Vector2? indica que el parámetro puede ser del tipo Vector2 o
un null. Ésta importante novedad, los tipos nulleables fue agregada hace unos años, haciendo
posible hacer null las variables por valor.
Lo mencionado en éste caso tiene su razón: cualquier modificación mediante herencia hecha
por terceros en estas clases haría que prácticamente fuera imposible compatibilizar los cientos
o miles de soluciones posibles, es decir, cada uno haría lo que querría y eso conduciría al caos.
Dicha clase no podrá ser instanciada, ni se podrá obviamente tener variables de dicho tipo.
Solo debe tener en cuenta que la accesibilidad del miembro reemplazado debe respetarse en
las clases hijas.
virtual
En la POO es usual que se creen objetos padres que contengan métodos declarados con un
algoritmo que resuelve una situación básica, pero con antelación se prevé que se necesitará en
algunas de las clases hijas una solución o algoritmo diferente. Para éstas situaciones se pueden
declarar métodos o propiedades virtuales como el siguiente:
Formas de Declaración Descripción
public virtual int Health {
get Aquí la propiedad Health de los objetos plausibles de ser
{ destruidos, como los aliens y el jugador, se declara como
return health;
virtual, ya que es posible que alguna clase a futuro
}
set requiera un comportamiento distinto al implementado en
{ ésta clase.
if (Shield <= 0) En particular, aquí en el sub método set se implementa la
health -= value;
else lógica del escudo de energía shield, el cual, siempre que
Shield -= value; esté activo impedirá que la energía health del objeto bajo,
} a expensas de parte del escudo de energía.
}
Casteo
Gracias a la herencia es posible manipular objetos que han heredado de una cierta clase con
una referencia del tipo de su clase padre. Esto es muy útil debido a que a veces no es
necesario saber exactamente de qué subclase es un dado objeto, solo basta con transportarlo
y manipularlo usando los miembros disponibles en su clase base.
Por ejemplo, dado que object es la clase base de todos los objetos de .Net, es posible pasar
una referencia de cualquier cosa en un método que utiliza un parámetro de éste tipo. No es
casualidad que en los métodos asociados a eventos uno de los parámetros sea de éste Tipo,
como se puede ver debajo:
Forma de Declaración
Descripción
El evento de Scroll de un VerticalScrollBar es capturado por el método mostrado. El primer
parámetro denominado sender es del tipo Object, y está pensado para transportar una
referencia del Objeto que genera el Evento, el cual puede ser de cualquier Tipo.
A veces se desea acceder a los miembros del objeto heredado no disponibles en el Tipo del
objeto utilizado, como se ve debajo.
Forma de Declaración
Descripción
Observe que ahora luego del Casteo todos los miembros del objeto control están disponibles,
aunque sender no sea un control.
Obviamente, antes de Castear al objeto debemos asegurarnos de que sea del Tipo al cual
pretendemos Castear, ya que si no saltará una Excepción.
Para ello recurrimos a una clausula donde preguntamos si el Tipo del objeto sender es …
(Control en el ejemplo)
Niveles de Acceso
Permiten que los miembros u objetos sean accesibles o no externamente a los objetos o
Ensamblados (Bibliotecas o Ejecutables) que los contienen.
Las opciones posibles ordenadas por nivel de accesibilidad decreciente son:
Nivel de Acceso Accesibilidad
public Es accesible dentro y fuera de la Clase o Biblioteca según corresponda.
Internal Es accesible solo por objetos dentro del Ensamblado
No es accesible fuera de la clase, pero si es heredable y accesible
protected
internamente por una clase heredada o hija
No es accesible fuera de la clase (en el caso de los miembros) o de la
private
Biblioteca (para una Clase o Estructura).
Métodos
Las antiguas funciones y subrutinas se agrupan ahora bajo el nombre de Método. Se trata de
un conjunto de líneas de código que pueden ser llamados a voluntad las veces que queramos y
pueden o no devolver objetos o valores.
Las más simples se declaran así:
Formas de Declaración Descripción
protected void DrawShield()
{ La palabra reservada void indica que el método no devuelve
⋮ nada luego de ejecutarse.
}
La palabra reservada int indica que el método devuelve un
protected int DrawHealth() valor entero luego de ejecutarse. Éste valor entero
{
probablemente brinda alguna información relevante a quien
⋮
} llamo el método.
El Tipo devuelto puede elegirlo el programador a voluntad.
Parámetros
Muchas veces es necesario pasar algún tipo de información a un método, y para ello existen
los denominados parámetros o argumentos. La cantidad y tipos de éstos no está restringida4.
Declaración Descripción
public void Shot(int shotrate) En este caso se pasa un parámetro tipo entero. El
{
parámetro solo puede utilizarse dentro del método, es
⋮
} decir, ese es su ámbito.
Internamente un parámetro se comporta como una variable mas, solo que el valor es seteado
fuera del método.
Los métodos reciben parámetros, y éstos pueden pasar bajo 2 formas bien distintas:
por valor
por referencia
4
El número de parámetros máximo puede ser tan grande que usualmente no es algo que preocupe a los
programadores.
Finalmente, la opción restante sería una variable por referencia pasada por referencia! Todo
indica que no existe una situación real donde ésta opción sea útil.
Sobrecarga
Una de las novedades frente a la programación tradicional es la posibilidad de crear varios
métodos u operadores con el mismo nombre, con la condición de que éstos tengan diferentes
tipos de parámetros o diferente cantidad de éstos.
Parámetros Opcionales
Una utilidad muy potente agregada algunos años atrás es la posibilidad de que los parámetros
sean opcionales. Se trata de una forma más de sobrecarga, y se muestra su uso a continuación:
Declaración Descripción
Simplemente se hace asignándole el valor por
protected void Shot(int shotrate = 30) omisión al parámetro. La condición necesaria
{
⋮ es que siempre si hay varios parámetros a
} partir del primero opcional el resto de los
parámetros también deben ser opcionales.
Obviamente cualquiera que sepa programar un poco podría observar acertadamente que ¡no
existe aparentemente diferencias sustanciales entre la forma de uso mostrada de la propiedad
y por ejemplo una variable miembro publica! por ejemplo:
Forma de uso de la propiedad Forma de uso de la variable (debería cambiarse a publica)
heroe.Health = 90; item.health = 90;
Dejamos que el lector reflexione acerca del uso correcto de la primera e incorrecto en la
segunda, así como las ventajas y desventajas de cada una!
Auto propiedades
Como la mayoría de las propiedades involucran a una variable y al getter y setter sin más
código accesorio, en 2008 incluyeron esta variante de propiedades que permiten declarar lo
mismo con muchas menos palabras:
Formas de Declaración Descripción
En esencia se comportan como las propiedades CLR,
pero como podrá apreciar, la reducción de código es
public int Shield { get; set; }
significativa. En el caso de que necesite algún código de
verificación deberá recurrir a las propiedades CLR.
También son admisibles las autopropiedades de solo lectura y solo escritura, pero lo más
curioso son las que poseen getter y setter con distinto nivel de accesibilidad, por ejemplo:
Formas de Declaración Descripción
Como podrá deducir, el get es public,
accesible por cualquiera, pero el set es
public int Shield { get; protected set; }
protected, solo accesible desde dentro de
la clase o desde sus clases hijas.
En la práctica es muy difícil encontrar ejemplos reales de propiedades de solo escritura, ya que
cuesta pensar que nunca se deseará leer el valor de dicha propiedad.
5
value es un parámetro implícito porque nunca fue declarado en ningún lugar del código, siendo quizás
una de las inconsistencias menores del C#, cosa que no se da en su lenguaje hermano en desuso Visual
Basic .Net, donde el parámetro es explicito.
Clase A
En el esquema previo se aprecian dos clases, la primera contiene un método estándar sin
parámetros denominado metodotarget.
La segunda contiene la declaración del tipo delegado al cual se lo llamo tipodelegado y una
variable de dicho tipo llamada variabledelegado.
Solo restaría inicializar la variable variabledelegado con una referencia al método blanco
metodotarget.
Declaración de un Delegado
En la declaración de éstos se indica el formato de los métodos que pueden ser referenciados
(lo que a menudo se denomina firma o signature) y luego invocados, es decir, se indica el tipo
devuelto y los parámetros en cantidad, orden y Tipo. Se utiliza para ello la palabra reservada
delegate, como se muestra debajo:
Declaración
Descripción
En éste caso hemos declarado un delegado de un método con 2 parámetros, el cual no
devuelve nada.
NOTA
Tenga presente que, la declaración de los delegados no están restringidas a estar
dentro de una clase, sino que pueden declararse también fuera de éstas.
delegado variabledelegado;
public BackGround()
{
variabledelegado = metodotarget;
}
NOTA
El ejemplo mostrado solo tiene fines didácticos y no está relacionado con el juego
utilizado para el resto de los ejemplos, ya que no tenía sentido usar delegados en
dicho juego.
Conclusión
La potencia real de los delegados radica en que, en general de antemano no se conoce cuál
será el método Target, pudiéndose entonces elegir cualquier método que cumpla las
condiciones
Además, es posible en la mayoría de los casos cambiar de método Target en tiempo de
ejecución.
Llamada directa a
método público
Objeto YY 1
Función Pública
expuesta
Objeto XX 1
Evento
Como podrá imaginar, la potencia de esto es increíble, ya que dinámicamente puedo suscribir
y eliminar la suscripción cuando lo desee.
Para dejar de capturar el evento hay que usar el operador -=.
Obviamente, si por error subscribo N veces un evento a un determinado método, cada vez
que el evento suceda el método será llamado también N veces.
namespace WpfTragamonedas
{
/// <summary>
/// Lógica de interacción para MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
Controles Básicos
Figura 48. Vista del ToolBox
Para darle una mejor apariencia y funcionalidad a
nuestra aplicación procederemos a incluir algunos
controles.
Para ello debemos desplegar el Cuadro o Panel de
Herramientas (ToolBox) donde podremos
observar una gran variedad de controles
disponibles.
Entre los más simples y los más utilizados
tenemos:
Label
Button
TextBox
Calendar
Image
CheckBox
StackPanel
TextBlock
ComboBox
ListBox
Grid
Al dibujar o arrastrar el control al formulario se generará un código XML asociado a este, por
ejemplo:
Vista del código XML generado, asociado al TextBlock
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid>
<TextBlock HorizontalAlignment="Left" Margin="27,73,0,0"
TextWrapping="Wrap"
Text="TextBlock" VerticalAlignment="Top"/>
</Grid>
</Window>
El código XML que debió agregarse para conseguir lo mostrado se observa debajo:
Código asociado al formulario
<Window x:Class="WpfTragamonedas.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfTragamonedas"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Grid>
<TextBlock Text="Hola, buen dia" Margin="10,17,42,131"
Background="#FF8DDA57" />
<Button Click="Button_Click" Content="Empezar" Margin="10,202,385,87" />
</Grid>
</Window>
Funcionalmente de momento no hace nada, pero permite mostrar como en muy poco tiempo
y con poco esfuerzo se puede lograr una aplicación con apariencia agradable al usuario final.
Aquí también podemos ver al muy útil evento Click, que se puede apreciar en la Figura 51.,
junto a una descripción de la clase o miembro seleccionado.
Menús
La inclusión de un menú es simple, ya que se trata de un control más llamado simplemente
Menu.
Si hacemos Click sobre éste, luego lo dibujamos o arrastramos al formulario, y finalmente
agregamos los ítems del menú nos queda:
Figura 52. Vista del Menú agregado y sus sub items
Como podrá observar, es sumamente fácil crear un menú con el diseñador. Ahora solo resta
agregar código para que algo suceda al presionar sobre la etiqueta del menú.
Para ello hacemos doble clic en la etiqueta deseada (en la primera en nuestro caso), entonces
el diseñador se encargará de crear el método asociado al clic de la etiqueta, lo que luce así:
Método que captura el clic sobre el ítem de menú Nuevo
private void MenuItem_Click(object sender, RoutedEventArgs e)
{
⋮
}
Cuadros de dialogo
Los cuadros de diálogo básicos están disponibles mediante código mediante la siguiente
sentencia:
Formas de Declaración
private void MenuItem_Click(object sender, RoutedEventArgs e)
{
if (MessageBox.Show("Desea continuar?",
"Atención!",
MessageBoxButton.OKCancel) == MessageBoxResult.OK)
⋮
} Falta algún código!!
Como resultado de ejecutar dicha línea obtenemos:
La sentencia pregunta por el resultado del cuadro de
Figura 53. Vista del MessageBox
diálogo (un valor del tipo MessageBoxResult que indica
el botón presionado, MessageBoxResult.OK o
MessageBoxResult.Cancel en este caso).
Tenga en cuenta que luego del if debe agregar código
para cuando el usuario acepta lo que indica este cuadro
de dialogo.
ANEXO 1
Debug Programming o Execution Time Programming
Una metodología de programación solo difundida entre algunos pocos es la Programación
durante la Depuración o Programación en Tiempo de Ejecución.
Mediante esta técnica se escribe código, generalmente solo el de algún algoritmo en
particular, el cual por lo general es algo complicado, y se hace durante la ejecución y
depuración del programa.
Esto en Visual Studio, en los lenguajes .Net es totalmente viable, ya que en tiempo de
ejecución este entorno permite editar el código fuente, borrando o agregando variables o
líneas al algoritmo deseado.
Entre las operaciones y herramientas que tenemos en tiempo de depuración podemos citar:
Línea en ejecución
Breack Point
Como observará, tras presionar el botón button1 la ejecución del código se detiene en la
línea donde se halla el Breack Point (la línea actual en ejecución está toda marcada en
amarillo), permitiendo que el usuario inspeccione variables y tome decisiones sobre si el
código es correcto o se deben hacer modificaciones en éste.
En el siguiente grafico, el programador mueve el puntero a instrucción a otra línea, haciendo
que la del breack point no se ejecute:
Figura 55. Cambio del puntero a instrucción mediante el mouse
Breack Point
Puntos de Interrupción
Se denominan puntos de interrupción o Breack Points a aquellos lugares específicos en las
líneas del código fuente donde la ejecución del programa se detendrá, condicional o
incondicionalmente, para que el programador inspeccione el código aledaño.
En la grafica anterior se presentó ya un punto de interrupción, marcado con un punto y la línea
de código en color marrón, pero la novedad aquí es un Panel que permite ver todos los Breack
Points así como su estado y estadísticas, tal como se aprecia a continuación:
Figura 56. Vista del Panel de Puntos de Interrupción
Observe que en este caso el último de los puntos de interrupción es condicional, es decir, que
solo bajo ciertas circunstancias detendrá la ejecución del código, en este caso cuando la
variable a sea menor que 10.
También es posible, mediante este panel, deshabilitar o habilitar los breack points a voluntad,
según las necesidades de depuración del momento.
Con esta condición solo se detendrá la ejecución mientras el valor de la variable a sea menor
que 10.
Como verá, no solo se insertaron nuevas líneas, sino que se declaro una variable nueva, se
inserto un bucle, y se des comentó una línea antes comentada.
Mediante el cursor
La forma más simple de chequear o ver el estado o valor de una variable es posicionándose
con el cursor sobre ésta, como se ve debajo:
Figura 61. Inspección de variables mediante el uso del cursor
Para modificar el valor de una variable numérica o tipo string, solo es necesario escribir el
nombre de la variable, el signo igual = y el valor a asignar
También es posible ejecutar un método simplemente escribiendo la línea de código que llama
a ese método y presionar Enter.
Panel de Inspección
Muy similar al anterior, solo que se agrega a un listado en un panel que permite ver la
evolución de la variable cuando se ejecuta paso a paso. Debajo hay un ejemplo de dicha vista:
Figura 63. Uso del Panel de Inspección para la revisión de variables
Observe que junto a la variable a hay una segunda variable b que no se halla definida en el
contexto analizado (dentro de la función que se ejecuta).
Variable a inspeccionar
Tal como se ve, la variable, junto a su contenido público, variables y propiedades, puede
examinarse a voluntad, y a veces inclusive se puede modificar el valor de algunas de éstas.
También, donde aparecen Nodos extras en el árbol, es posible examinar los miembros del
objeto inspeccionado originalmente, como en este caso podría ser el button1 o el button2.