ventajas usos usar tipos tipo runtimebinderexception runtimebinder puede programacion microsoft los invocar hilos funcionan funcion delegate delegados delegado csharp concepto como c# delegates

c# - usos - ¿Cómo trabajan los delegados(en el fondo)?



tipos de delegates (6)

¿Cómo trabajan los delegados en c # detrás de escena y cómo pueden usarse de manera eficiente?

EDITAR: Sé cómo funcionan en la superficie (básicamente son punteros de función y permiten invocar métodos de devolución de llamada con ciertas firmas usando su dirección). Lo que necesito saber es cómo el CLR realmente los implementa internamente. ¿Qué sucede exactamente detrás de las escenas cuando defines un delegado y cuando invocas un método de devolución de llamada usando el objeto delegado?


El compilador de C # genera una clase completa cuando creas un delegado. Esta clase contiene una lista de referencias de funciones, como mencionó Konrad. Lo bueno de los delegados es que le proporcionan una manera fácil de ejecutar la tarea de forma asíncrona con devolución de llamadas de notificación. Lo que esto significa es que se le puede notificar cuando finalice su operación en segundo plano. Threadpool no proporciona esta característica. Los delegados son un tema amplio y encuentro que los libros de Jeff Richter (CLR vía C #) y Albahari (C # 3) son de especial ayuda.


Los delegados de C # son objetos (consulte la clase System.Delegate) que encapsulan una referencia a un objeto y un puntero de método. También pueden tener una referencia nula al objeto para representar una llamada a un método estático.

Al invocar al delegado con argumentos, el delegado crea una llamada al método al que se hace referencia en el objeto al que se hace referencia con argumentos especificados.

Un método de invocación de delegado compilado se maneja directamente por el tiempo de ejecución (como es visible con Reflector):

[MethodImpl(0, MethodCodeType=MethodCodeType.Runtime)] public virtual void Invoke(T obj);

El tiempo de ejecución utiliza toda la información interna para compilar una llamada de método estándar al método al que se hace referencia.


Los delegados en C # son listas de punteros de método. Es decir, almacenan referencias al código, y puede invocar los métodos a través de los punteros. Esto es útil en muchos casos. El ejemplo común es para los manejadores de eventos donde los delegados se utilizan para implementar un patrón de editor / suscriptor.


Re eficiencia: no está claro a qué se refiere, pero se pueden usar para lograr la eficiencia, evitando la reflexión costosa. Por ejemplo, al usar Delegate.CreateDelegate para crear un delegado preestablecido (escrito a máquina) en un método dinámico / buscado, en lugar de usar el (más lento) MethodInfo.Invoke .

Para un ejemplo trivial (accediendo al patrón T Parse(string) estático para un tipo), ver a continuación. Tenga en cuenta que solo utiliza la reflexión una vez (por tipo), en lugar de muchas veces. Esto debería TypeConverter reflejo o el uso típico de TypeConverter :

using System; using System.Reflection; static class Program { // formatted for space static void Main() { // do this in a loop to see benefit... int i = Test<int>.Parse("123"); float f = Test<float>.Parse("123.45"); } } static class Test<T> { public static T Parse(string text) { return parse(text); } static readonly Func<string, T> parse; static Test() { try { MethodInfo method = typeof(T).GetMethod("Parse", BindingFlags.Public | BindingFlags.Static, null, new Type[] { typeof(string) }, null); parse = (Func<string, T>) Delegate.CreateDelegate( typeof(Func<string, T>), method); } catch (Exception ex) { string msg = ex.Message; parse = delegate { throw new NotSupportedException(msg); }; } } }


Cuando defines a tu delegado

internal delegate void Feedback(Int32 value);

el compilador realmente define una clase completa que se ve así:

internal class Feedback : System.MulticastDelegate { // Constructor public Feedback(Object object, IntPtr method); // Method with same prototype as specified by the source code public virtual void Invoke(Int32 value); // Methods allowing the callback to be called asynchronously public virtual IAsyncResult BeginInvoke(Int32 value, AsyncCallback callback, Object object); public virtual void EndInvoke(IAsyncResult result); }

Fuente: Jeffrey Richter - CLR a través de C # , capítulo 17


La primera parte de la pregunta es relativamente fácil: los delegados almacenan una lista de indicadores de función. Si invoca a un delegado, llama a todos los punteros de función en esa lista interna. Agregar y eliminar un receptor (a través de Delegate.Combine y Delegate.Remove ) equivale a agregar y eliminar de esa lista.

Para obtener más información de bajo nivel, consulte ECMA-335 (el estándar CLI), sección II.14.5 (Punteros del método) y II.14.6 (Delegados). En particular, tenga en cuenta que un delegado consiste en un puntero de instancia (de tipo System.Object ) y un puntero de método (de tipo System.IntPtr ). Se puede obtener un puntero de método (en CIL) a través de las ldftn o ldvirtftn (para llamadas a funciones virtuales).

Estas dos piezas de información identifican cualquier método.

¿cómo se pueden usar de manera eficiente?

¿Qué quieres decir con eso? ¿Conoces los eventos o tu pregunta es más especializada?