Calificación:
  • 0 voto(s) - 0 Media
  • 1
  • 2
  • 3
  • 4
  • 5
[Tutorial] C# Delgados [Intermedio-Semiprofesional]
#1


Tutorial de delegados
Visual Studio .NET 2003
Este tutorial trata sobre los tipos delegados. Se explica cómo asignar delegados a métodos de instancia y estáticos y cómo combinarlos (multidifusión).

Archivos de ejemplo

Vea Ejemplo de delegados para descargar y generar los archivos de ejemplo que se utilizan en este tutorial.

Información adicional

delegate
15. Delegados
Tutorial de eventos
Delegados asincrónicos
Tutorial

Un delegado en C# es similar a un puntero a una función en C o C++. El uso de un delegado permite al programador encapsular una referencia a un método dentro de un objeto delegado. El objeto delegado se puede pasar entonces al código, el cual puede llamar al método de referencia, sin tener que conocer en tiempo de compilación qué método se debe invocar. A diferencia de los punteros a función de C o C++, los delegados están orientados a objetos, proporcionan seguridad de tipos y son seguros.

Una declaración de delegado define un tipo que encapsula un método con un determinado conjunto de argumentos y un tipo devuelto. Para métodos estáticos, un objeto delegado encapsula el método que se debe llamar. Para métodos de instancia, un objeto delegado encapsula tanto una instancia como un método de la instancia. Si dispone de un objeto delegado y un conjunto apropiado de argumentos, puede invocar el delegado con los argumentos.

Una propiedad interesante y útil de un delegado es que no necesita conocer la clase del objeto al que hace referencia. Cualquier objeto es adecuado; lo único que importa es que los tipos de los argumentos del método y el tipo devuelto coincidan con los del delegado. Esto hace que los delegados sean perfectos para una invocación "anónima".

Nota Los delegados se ejecutan bajo los permisos de seguridad de los llamadores, no de los declaradores.
Este tutorial incluye dos ejemplos:

El Ejemplo 1 muestra cómo declarar, crear instancias y llamar a un delegado.
El Ejemplo 2 muestra cómo combinar dos delegados.
Además, este tutorial trata de los siguientes temas:

Delegados y eventos
Delegados frente a interfaces
Ejemplo 1

El siguiente ejemplo ilustra la declaración, creación de instancias y uso de un delegado. La clase BookDB encapsula una base de datos de los libros de una librería. Expone un método ProcessPaperbackBooks, el cual busca todos los libros en edición rústica de la base de datos y llama a un delegado para cada uno. El tipo delegate que se utiliza se denomina ProcessBookDelegate. La clase Test utiliza esta clase para imprimir los títulos y el precio medio de los libros en rústica.

El uso de delegados promueve una buena separación de la funcionalidad entre la base de datos de la librería y el código del programa cliente. El código del cliente no tiene conocimiento de cómo están almacenados los libros ni de cómo busca el código de la librería de los libros en rústica. El código de la librería no conoce qué procesamiento se realiza sobre los libros en rústica después de encontrarlos.

// bookstore.cs
using System;

// A set of classes for handling a bookstore:
namespace Bookstore
{
using System.Collections;

// Describes a book in the book list:
public struct Book
{
public string Title; // Title of the book.
public string Author; // Author of the book.
public decimal Price; // Price of the book.
public bool Paperback; // Is it paperback?

public Book(string title, string author, decimal price, bool paperBack)
{
Title = title;
Author = author;
Price = price;
Paperback = paperBack;
}
}

// Declare a delegate type for processing a book:
public delegate void ProcessBookDelegate(Book book);

// Maintains a book database.
public class BookDB
{
// List of all books in the database:
ArrayList list = new ArrayList();

// Add a book to the database:
public void AddBook(string title, string author, decimal price, bool paperBack)
{
list.Add(new Book(title, author, price, paperBack));
}

// Call a passed-in delegate on each paperback book to process it:
public void ProcessPaperbackBooks(ProcessBookDelegate processBook)
{
foreach (Book b in list)
{
if (b.Paperback)
// Calling the delegate:
processBook(b);
}
}
}
}

// Using the Bookstore classes:
namespace BookTestClient
{
using Bookstore;

// Class to total and average prices of books:
class PriceTotaller
{
int countBooks = 0;
decimal priceBooks = 0.0m;

internal void AddBookToTotal(Book book)
{
countBooks += 1;
priceBooks += book.Price;
}

internal decimal AveragePrice()
{
return priceBooks / countBooks;
}
}

// Class to test the book database:
class Test
{
// Print the title of the book.
static void PrintTitle(Book b)
{
Console.WriteLine(" {0}", b.Title);
}

// Execution starts here.
static void Main()
{
BookDB bookDB = new BookDB();

// Initialize the database with some books:
AddBooks(bookDB);

// Print all the titles of paperbacks:
Console.WriteLine("Paperback Book Titles:");
// Create a new delegate object associated with the static
// method Test.PrintTitle:
bookDB.ProcessPaperbackBooks(new ProcessBookDelegate(PrintTitle));

// Get the average price of a paperback by using
// a PriceTotaller object:
PriceTotaller totaller = new PriceTotaller();
// Create a new delegate object associated with the nonstatic
// method AddBookToTotal on the object totaller:
bookDB.ProcessPaperbackBooks(new ProcessBookDelegate(totaller.AddBookToTotal));
Console.WriteLine("Average Paperback Book Price: ${0:#.##}",
totaller.AveragePrice());
}

// Initialize the book database with some test books:
static void AddBooks(BookDB bookDB)
{
bookDB.AddBook("The C Programming Language",
"Brian W. Kernighan and Dennis M. Ritchie", 19.95m, true);
bookDB.AddBook("The Unicode Standard 2.0",
"The Unicode Consortium", 39.95m, true);
bookDB.AddBook("The MS-DOS Encyclopedia",
"Ray Duncan", 129.95m, false);
bookDB.AddBook("Dogbert's Clues for the Clueless",
"Scott Adams", 12.00m, true);
}
}
}
Resultado

Paperback Book Titles:
The C Programming Language
The Unicode Standard 2.0
Dogbert's Clues for the Clueless
Average Paperback Book Price: $23.97
Descripción del código

Declarar un delegado La siguiente instrucción:
public delegate void ProcessBookDelegate(Book book);
declara un nuevo tipo delegado. Cada tipo delegado describe el número y tipo de los argumentos, así como el tipo del valor devuelto de los métodos que puede encapsular. Cuando se necesita un nuevo conjunto de tipos de argumentos o de valor devuelto, se debe declarar un nuevo tipo delegado.

Crear una instancia de un delegado Una vez declarado un tipo delegado, debe crearse un objeto delegado y asociarlo con un determinado método. Al igual que los demás objetos, un objeto delegado se crea mediante una expresión new. Sin embargo, cuando se crea un delegado, el argumento que se pasa a la expresión new es especial: se escribe como una llamada a un método, pero sin los argumentos.
La siguiente instrucción:

bookDB.ProcessPaperbackBooks(new ProcessBookDelegate(PrintTitle));
crea un objeto delegado asociado con el método estático Test.PrintTitle. La siguiente instrucción:

bookDB.ProcessPaperbackBooks(new
ProcessBookDelegate(totaller.AddBookToTotal));
crea un objeto delegado asociado con el método no estático AddBookToTotal sobre el objeto totaller. En ambos casos, este nuevo objeto delegado se pasa inmediatamente al método ProcessPaperbackBooks.

Observe que una vez que se crea el delegado, el método con el que está asociado no cambia nunca (los objetos delegados son inmutables).

Llamar a un delegado Una vez creado un objeto delegado, éste se pasa normalmente a otro código que llamará al delegado. La llamada a un objeto delegado se realiza mediante el nombre del objeto delegado, seguido por los argumentos entre paréntesis que se pasarán al delegado. Un ejemplo de llamada a un delegado es:
processBook(b);
Se puede llamar a un delegado de forma sincrónica, como en este ejemplo, o de forma asincrónica, utilizando los métodos BeginInvoke y EndInvoke.

Ejemplo 2

Este ejemplo muestra cómo componer delegados. Una propiedad útil de los objetos delegados es que se pueden componer mediante el operador "+". Un delegado compuesto llama a los dos delegados de los que se compone. Solo pueden ser compuestos los delegados del mismo tipo.

El operador "-" se puede utilizar para quitar un delegado componente de un delegado compuesto.

// compose.cs
using System;

delegate void MyDelegate(string s);

class MyClass
{
public static void Hello(string s)
{
Console.WriteLine(" Hello, {0}!", s);
}

public static void Goodbye(string s)
{
Console.WriteLine(" Goodbye, {0}!", s);
}

public static void Main()
{
MyDelegate a, b, c, d;

// Create the delegate object a that references
// the method Hello:
a = new MyDelegate(Hello);
// Create the delegate object b that references
// the method Goodbye:
b = new MyDelegate(Goodbye);
// The two delegates, a and b, are composed to form c:
c = a + b;
// Remove a from the composed delegate, leaving d,
// which calls only the method Goodbye:
d = c - a;

Console.WriteLine("Invoking delegate a:");
a("A");
Console.WriteLine("Invoking delegate b:");
b("B");
Console.WriteLine("Invoking delegate c:");
c("C");
Console.WriteLine("Invoking delegate d:");
d("D");
}
}
Resultado

Invoking delegate a:
Hello, A!
Invoking delegate b:
Goodbye, B!
Invoking delegate c:
Hello, C!
Goodbye, C!
Invoking delegate d:
Goodbye, D!
Delegados y eventos

Los delegados son ideales para su uso como eventos (notificaciones de un componente a sus "receptores" sobre los cambios que se producen en ese componente). Para obtener más información acerca del uso de delegados para eventos, vea Tutorial de eventos.

Delegados frente a interfaces

Delegados e interfaces son similares en el sentido en que ambos permiten la separación entre especificación e implementación. Varios programadores independientes pueden crear implementaciones compatibles con una especificación de interfaz. De forma similar, un delegado especifica la firma de un método, y los programadores pueden escribir métodos compatibles con la especificación del delegado. ¿Cuándo se deben utilizar interfaces y cuándo delegados?

Los delegados son útiles cuando:

Se llama a un único método.
Una clase necesita varias implementaciones de la especificación del método.
Es deseable permitir el uso de un método estático para implementar la especificación.
Se desea utilizar un modelo de diseño similar al de los eventos (para obtener más información, vea el Tutorial de eventos).
El código que realiza la llamada no necesita conocer u obtener el objeto sobre el que el método está definido.
El proveedor de la implementación desea "distribuir" la implementación de la especificación sólo a unos pocos componentes seleccionados.
Se desea conseguir una composición fácil.
Las interfaces son útiles cuando:

La especificación define un conjunto de métodos relacionados a los que se llamará.
Una clase normalmente implementa la especificación sólo una vez.
El código que realiza la llamada a la interfaz necesita convertir hacia o desde el tipo de la interfaz para obtener otras interfaces o clases.


Posibles temas similares...
Tema Autor Respuestas Vistas Último mensaje
Información [Tutorial] Certificado SSL Gratis StartSSL 2016 Tutorial DarkMaster 26 5,130 28-04-2016, 03:39 AM
Último mensaje: Lob3zNo
Bombilla [Tutorial] SSL Gratis, Conseguir e Instalar Certificado DarkMaster 16 873 06-01-2016, 01:32 AM
Último mensaje: DarkMaster
  [PUBLICO] Tutorial Botones con perspectiva 3D AngelKrak 0 235 17-01-2015, 05:44 AM
Último mensaje: AngelKrak
  [Tutorial] Aumentar el Tamaño Máximo al Cargar Archivos con PHP y Apache papanoel 0 671 22-01-2014, 04:38 AM
Último mensaje: papanoel
  Tutorial Css Primera Parte para phpost JNeutron 4 1,053 24-02-2013, 04:01 AM
Último mensaje: Echizen
  [TUTORIAL] Conexión a una Base de Datos desde [PHP] lapipichapa 0 492 15-02-2013, 05:52 PM
Último mensaje: lapipichapa
  Tutorial de .htaccess | Control de acceso a carpetas diringax 11 1,454 13-01-2013, 12:28 PM
Último mensaje: papi
  [TUTORIAL] Como evitar el Hotlinkeo (robo de imágenes) Taquion 8 1,690 12-01-2013, 05:50 PM
Último mensaje: natestale
  Tutorial | Crear Sistema de Login PHP diringax 13 1,741 18-12-2012, 01:49 AM
Último mensaje: BrayanFG
  [Tutorial] Dominios virtuales para localhost Alan71 25 2,209 18-12-2012, 01:44 AM
Último mensaje: BrayanFG



Usuarios navegando en este tema: 1 invitado(s)