Académique Documents
Professionnel Documents
Culture Documents
NET - Parte I
Contenido
Antes del advenimiento de la plataforma .NET, Visual Basic era el rey (al menos en el reino del desarrollo de
software para plataforma Microsoft). Cerca del 80% de las aplicaciones de negocios a nivel mundial estaban
(y muchas siguen estando) escritas en ese lenguaje. Sin embargo, muchos programadores acostumbrados a
la complejidad -y flexibilidad- de lenguajes de más bajo nivel (como C++) criticaban a Visual Basic por no
permitir un mayor control sobre la forma en que se estructura y codifica el software. "Visual Basic es muy
tieso", decían. Y tenían razón. Visual Basic está orientado a la funcionalidad del producto (no a su
arquitectura). Lo anterior enfurecía a quienes deseaban un mayor control sobre los recursos de la máquina,
las estructuras de programación, e incluso sobre la propia forma en la que el código fuente se traduce a
código máquina. Con Visual Basic se podía crear aplicaciones mucho más rápido que en C++ (por ejemplo)
pero dichas aplicaciones rara vez era más eficientes, escalables e incluso portables que las escritas en
lenguajes de más bajo nivel. Con la llegada de la plataforma .NET, esta situación cambió.
.NET brinda al programador un mayor control sobre la forma en que su código accede a los recursos, utiliza
las estructuras y técnicas de programación e, incluso, se traduce a lenguaje intermedio (el lenguaje de la
plataforma .NET).
Principio de la página
2. Delegados
Un delegado es una estructura de programación que nos permite invocar a uno o varios métodos a la vez.
Estos métodos pueden encontrarse en la misma clase desde la que se invocan o en clases distintas asociadas
a ésta. Hablando "a bajo nivel", un delegado es un puntero seguro a una función (pero sin la complejidad de
la administración propia de dicho puntero).
Principio de la página
Gestión de eventos
Quizás éste sea el principal uso de los delegados. Notificar a uno o varios componentes el acontecimiento de
un determinado evento con el fin de que dichos componentes tomen alguna acción al respecto. Este es el
fundamento de la programación orientada a eventos (uno de los pilares de la programación visual).
Utilizando eventos, los componentes de la interfaz avisan a la lógica de negocios que el usuario ha ejecutado
alguna acción sobre los componentes de la misma (por ejemplo, presionar el botón del mouse o presionar
una tecla).
msdn.microsoft.com/…/bb972282.aspx 1/6
18/06/2010 Delegados en .NET - Parte I
Implementación de patrones de diseño
Existen muchos patrones de diseño basados en eventos (posiblemente el más conocido sea el patrón
"Publicador-Suscriptor"). Utilizando eventos y delegados se puede establecer un mecanismo que permita
que una clase interesada en los servicios de otra reciba una notificación instantánea en el momento en que
acontezca un acontecimiento sobre el cual deba tomar alguna acción (por ejemplo, recibir una notificación
cuando se realice una operación sobre una cuenta bancaria).
Llamadas asíncronas
La invocación a un componente relacionado puede tomar mucho tiempo en recibir respuesta. Esto sucede
muchas veces cuando se manipulan grandes cantidades de datos o cuando la lógica del servicio que se
invoca es extremadamente compleja. Lo más "triste" de esta situación es que muchas veces no requerimos la
respuesta a dicha invocación para seguir trabajando, o bien, podemos realizar otras tareas mientras
esperamos por ella. En estos casos podemos pasar el puntero a una función ("Perdón ... ¿Dijo un delegado?")
para que en el momento en que el método invocado finalice su ejecución llame a la función que le fue pasada
(utilizando su dirección o puntero) con el fin de indicar que ha terminado su trabajo.
A estos punteros a funciones que se pasan a otro método para que éste indique su finalización, se les conoce
como "Funciones de retorno" (callback functions). Las funciones de retorno son el fundamento de la
invocación asíncrona entre componentes (Web Services y .NET Remoting) en .NET.
Métodos anónimos
Los programadores aficionados al paradigma funcional amarán esta funcionalidad incorporada en la reciente
versión del .NET Framework (la 2.0). ¿Porqué? Porque es la antesala de la llegada de las famosas funciones
Lambda omnipresentes y todo poderosas en los lenguajes funcionales a la plataforma .NET.
Un método anónimo en .NET es un método que es definido en aquel lugar en que se le ocupa. Es decir, no
contiene un encabezado, el código de dicho método se incorpora en el lugar en donde debería ir la
invocación a la función. Para lograr lo anterior se utilizan delegados.
Para obtener más detalles sobre esta nueva técnica, puedes acceder a la siguiente página:
http://msdn2.microsoft.com/en-us/vcsharp/default.aspx (al igual que el uso anterior, este tema será tratado en
mayor detalle en artículos posteriores).
Principio de la página
La sintaxis para la definición de delegados difiere según el lenguaje. No obstante, los conceptos
fundamentales que se mostrarán a continuación son invariables independientemente del lenguaje que se
utilice:
1. Lo primero que se debe hacer para definir un delegado es indicar cuál será la firma de las funciones a
la que ese delegado podrá apuntar (por firma se entiende el tipo de datos de los parámetros que se
reciben, y el tipo de datos que se retorna):
VB.NET
C#
[Nivel de protección] delegate [Tipo de retorno] NombreDelegado ([Tipo] Param1, Param2
[Tipo], ...)
msdn.microsoft.com/…/bb972282.aspx 2/6
18/06/2010 Delegados en .NET - Parte I
2. El segundo paso consiste en definir las variables que almacenarán los punteros de las funciones que se
invocarán a través del delegado. Para mayor claridad llamaremos a esta variable apuntador. Estas
variables deben ser del tipo de datos del delegado (definido en el paso anterior):
VB.NET
C#
[Nivel de protección] [Tipo Delegado] NombreApuntador
3. Una vez definida la firma del delegado y declarado el apuntador (variable del tipo de delegado) para
invocar las funciones, el tercer paso consiste en indicar cuáles serán esas funciones. Para eso se utiliza
el concepto de "sumar" métodos al apuntador (este concepto queda bastante evidente al observar la
sintaxis para realizar dicha operación en C#):
VB.NET
VB ofrece una sintaxis un poco más simple en el caso del uso de delegados para manejo
de eventos:
AddHandler NombreApuntador, AddressOf FuncionAAgregar
C#
NombreApuntador += new TipoDelegado(FuncionAAgregar)
4. Ya se puede invocar al apuntador, lo cual provocará la ejecución de todas las funciones que le hayan
sido agregadas. Para invocarlo simplemente basta con hacerlo por su nombre (pasándole los
parámetros requeridos definidos en la firma del delegado).
Principio de la página
5. Ejemplos
Para finalizar este artículo mostraremos dos ejemplos del uso de delegados para la gestión de eventos e
implementación del patrón "Publicador-Suscriptor" (los otros 2 usos mencionados en este artículo se tratarán
con mayor amplitud en posteriores artículos).
Gestión de eventos
En este ejemplo sólo el paso 3 es necesario. La razón de esto es que la variable apuntador para el evento
Click del botón (que de hecho recibe ese mismo nombre) ya se encuentra definida dentro de la clase
System.Windows.Forms.Button provista por el framework de .NET. El delegado al que corresponde dicho
apuntador (que es el mismo para los eventos de todos los controles gráficos) es de tipo
System.EventHandler. Es decir, para la gestión de eventos, lo único que se debe hacer es agregar al
apuntador de cada evento las funciones que serán invocadas cuando éste suceda. (Nota: Algunas secciones
del código han sido suprimidas para facilitar la comprensión del ejemplo):
VB .NET
Partial Class frmDelegados
Inherits System.Windows.Forms.Form
'<System.Diagnostics.DebuggerStepThrough()> _
Private Sub InitializeComponent()
Me.btnHolaMundo = New System.Windows.Forms.Button
Me.SuspendLayout()
'
msdn.microsoft.com/…/bb972282.aspx 3/6
18/06/2010 Delegados en .NET - Parte I
'btnHolaMundo
'
Me.btnHolaMundo.Location = New System.Drawing.Point(25, 12)
Me.btnHolaMundo.Name = "btnHolaMundo"
Me.btnHolaMundo.Size = New System.Drawing.Size(75, 23)
Me.btnHolaMundo.TabIndex = 0
Me.btnHolaMundo.Text = "Hola mundo"
Me.btnHolaMundo.UseVisualStyleBackColor = True
'inicio paso 3
AddHandler btnHolaMundo.Click, AddressOf ClickBotonHolaMundo
'fin paso 3
End Sub
End Class
C#
partial class frmDelegados
{
// inicio paso 3
this.btnHolaMundo.Click += new System.EventHandler(ClickBotonHolaMundo);
// fin paso 3
Patrón Publicador-Suscriptor
VB .NET
Clase Publicador:
Public Class Publicador
'Paso 1: Definir la firma del evento a publicar
Public Delegate Sub FirmaEventoAPublicar(ByVal texto As String)
msdn.microsoft.com/…/bb972282.aspx 4/6
18/06/2010 Delegados en .NET - Parte I
'Paso 4: Invocar las funciones agregadas a través del invocador
EventoAPublicar(texto)
End Sub
End Class
Clase Suscriptor:
Public Class Suscriptor
End Class
C#
Clase Publicador:
class Publicador
{
//Paso 1: Definir la firma del evento a publicar
public delegate void FirmaEventoAPublicar(string texto);
//Paso 2: Definir el apuntador para guardar las direcciones de las funciones a invoc
ar
public FirmaEventoAPublicar EventoAPublicar;
Clase Suscriptor:
class Suscriptor
{
public void AvisemeAqui(string texto)
{
MessageBox.Show("Gracias por avisar. Este es el mensaje recibido:" + texto);
}
}
msdn.microsoft.com/…/bb972282.aspx 5/6
18/06/2010 Delegados en .NET - Parte I
private Publicador unPublicador = new Publicador();
private Suscriptor unSuscriptor = new Suscriptor();
private Suscriptor otroSuscriptor = new Suscriptor();
Principio de la página
msdn.microsoft.com/…/bb972282.aspx 6/6