2009-01-29 26 views
8

Creo que entiendo el concepto de un delegado en C# como un puntero a un método, pero no puedo encontrar ningún buen ejemplo de dónde sería una buena idea usarlos. ¿Cuáles son algunos ejemplos que son significativamente más elegantes/mejores con los delegados o que no pueden resolverse utilizando otros métodos?C# - ¿Alguien puede decirme por qué y dónde debo usar delegados?

+0

Gosh, hice esta pregunta hace casi un año y ahora es difícil imaginar la vida antes de las expresiones delegados/lambda! Debo decir que las respuestas aquí siguen siendo algunos de los mejores ejemplos en la red. Tal es el poder de SO. – Alex

Respuesta

6

¿Qué es exactamente lo que quiere decir con delegados? Aquí hay dos maneras en las que pueden ser utilizados:

void Foo(Func<int, string> f) { 
//do stuff 
string s = f(42); 
// do more stuff 
} 

y

void Bar() { 
Func<int, string> f = delegate(i) { return i.ToString(); } 
//do stuff 
string s = f(42); 
// do more stuff 
} 

El punto en el que la segunda es que se puede declarar nuevas funciones sobre la marcha, como delegados. Esto puede ser reemplazado en gran medida por expresiones lambda, y es útil cada vez que tiene una pequeña porción de lógica que quiere 1) pasar a otra función, o 2) simplemente ejecutar repetidamente. LINQ es un buen ejemplo. Cada función LINQ toma una expresión lambda como su argumento, especificando el comportamiento. Por ejemplo, si tiene un List<int> l, entonces l.Select(x=>(x.ToString()) llamará a ToString() en cada elemento de la lista. Y la expresión lambda que escribí se implementa como un delegado.

El primer caso muestra cómo se podría implementar Select. Tomas a un delegado como argumento y luego lo llamas cuando sea necesario. Esto permite que el que llama personalice el comportamiento de la función. Tomando de nuevo Select() como ejemplo, la función en sí misma garantiza que se llamará al delegado que pase a cada elemento de la lista, y se devolverá el resultado de cada uno. Lo que ese delegado realmente hace depende de usted. Eso lo hace una función increíblemente flexible y general.

Por supuesto, también se usan para suscribirse a eventos. En pocas palabras, los delegados le permiten hacer referencia a las funciones, utilizándolas como argumento en llamadas a funciones, asignándolas a variables y cualquier otra cosa que quiera hacer.

6

Utilizo principalmente la programación fácil de asincronización. Iniciar un método usando el método Deleites Begin ... es realmente fácil si quieres disparar y olvidar.

Un delegado también se puede utilizar como una interfaz cuando las interfaces no están disponibles. P.ej. llamando a métodos de clases COM, clases .Net externas, etc.

0

no hay nada que resuelvan los delgados que no pueda resolverse con otros métodos, pero proporcionan una solución más elegante.

Con los delegados, se puede usar cualquier función siempre que tenga los parámetros necesarios.

La alternativa es a menudo utilizar un tipo de sistema de eventos hecha a la medida en el programa, la creación de trabajo extra y más áreas para los insectos a colarse en

11

.NET 1.0 delegados:

this.myButton.Click += new EventHandler(this.MyMethod); 

El .NET 2.0 delegates:

this.myOtherButton.Click += delegate { 
    var res = PerformSomeAction(); 
    if(res > 5) 
     PerformSomeOtherAction(); 
}; 

Parecen bastante útiles. ¿Qué tal:

new Thread(new ThreadStart(delegate { 
    // do some worker-thread processing 
})).Start(); 
+0

¡Eso es simplemente increíble! Entendido – SMUsamaShah

4

Los eventos son el ejemplo más obvio. Compare cómo se implementa el patrón de observador en Java (interfaces) y C# (delegados).

Además, muchas de las nuevas características de C# 3 (por ejemplo, expresiones lambda) se basan en delegados y simplifican aún más su uso.

3

Por ejemplo, en aplicaciones multiproceso. Si desea que varios hilos utilicen algún control, debe usar delegados. Lo sentimos, el código está en VisualBasic.

En primer lugar, declarar un delegado

Private Delegate Sub ButtonInvoke(ByVal enabled As Boolean) 

Escribir una función para habilitar el botón/desactivar desde varios hilos

Private Sub enable_button(ByVal enabled As Boolean) 
    If Me.ButtonConnect.InvokeRequired Then 

     Dim del As New ButtonInvoke(AddressOf enable_button) 
     Me.ButtonConnect.Invoke(del, New Object() {enabled}) 
    Else 
     ButtonConnect.Enabled = enabled 
    End If 

End Sub 
2

los uso todo el tiempo con LINQ, especialmente con las expresiones lambda, para proporcionar una función para evaluar una condición o devolver una selección. También utilícelos para proporcionar una función que compare dos elementos para clasificar. Esto último es importante para colecciones genéricas donde la clasificación por defecto puede o no ser apropiada.

var query = collection.Where(c => c.Kind == ChosenKind) 
         .Select(c => new { Name = c.Name, Value = c.Value }) 
         .OrderBy((a,b) => a.Name.CompareTo(b.Name)); 
2

Uno de los beneficios de Delegates es la ejecución asincrónica.

cuando llama a un método de forma asincrónica, no sabe cuándo finalizará la ejecución, por lo que necesita pasar un delegado a ese método que apunte a otro método que se invocará cuando el primer método haya completado la ejecución. En el segundo método, puede escribir un código que le informe que la ejecución se ha completado.

1

Algunas otras observaciones se refirió en el mundo asíncrono ... pero voy a comentar de todos modos ya mi 'sabor' favorita de hacer tal ha sido mencionado:

ThreadPool.QueueUserWorkItem(delegate 
{ 
    // This code will run on it's own thread! 
}); 

Además, una gran razón para los delegados es para "CallBacks". Digamos que hago un poco de funcionalidad (asíncrona), y que desea que llame a algún método (digamos "AlertWhenDone") ... que podría pasar en un "delegado" a su método de la siguiente manera:

TimmysSpecialClass.DoSomethingCool(this.AlertWhenDone); 
1

Fuera de su función en eventos, con los que probablemente esté familiarizado si utilizó winforms o asp.net, los delegados son útiles para hacer las clases más flexibles (por ejemplo, la forma en que se usan en LINQ).

La flexibilidad para "encontrar" cosas es bastante común. Tienes una colección de cosas, y quieres proporcionar una manera de encontrar cosas. En lugar de adivinar de qué manera alguien podría querer encontrar cosas, ahora puede permitir que la persona que llama proporcione el algoritmo para que puedan buscar su colección como lo consideren apropiado.

Aquí hay un ejemplo de código trivial:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 

namespace Delegates 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      Collection coll = new Collection(5); 
      coll[0] = "This"; 
      coll[1] = "is"; 
      coll[2] = "a"; 
      coll[3] = "test"; 

      var result = coll.Find(x => x == "is"); 

      Console.WriteLine(result); 

      result = coll.Find(x => x.StartsWith("te")); 

      Console.WriteLine(result); 

    } 

} 

public class Collection 
{ 
    string[] _Items; 

    public delegate bool FindDelegate(string FindParam); 

    public Collection(int Size) 
    { 
     _Items = new string[Size]; 

    } 

    public string this[int i] 
    { 
     get { return _Items[i]; } 
     set { _Items[i] = value; } 
    } 

    public string Find(FindDelegate findDelegate) 
    { 
     foreach (string s in _Items) 
     { 
      if (findDelegate(s)) 
       return s; 
     } 
     return null; 
    } 

} 
} 

salida

es

prueba

2

Técnicamente delegado es un tipo de referencia utilizado para encapsular un método con una firma específica y volver tipo

0

¿Hay alguna ventaja de utilizar un delegado cuando se trata de llamadas externas a una base de datos?

Por ejemplo, puede codificar A:

static void Main(string[] args) { 

      DatabaseCode("test"); 

} 

public void DatabaseCode(string arg) { 

      .... code here ... 

} 

mejorarse en el código B:

static void Main(string[] args) { 

      DatabaseCodeDelegate slave = DatabaseCode; 
      slave ("test"); 

} 

public void DatabaseCode(string arg) { 

      .... code here ... 

} 
public delegate void DatabaseCodeDelegate(string arg); 

Parece que esto es subjetivo, pero hay una zona donde hay fuertes puntos de vista conflictivos?

Cuestiones relacionadas