2011-03-25 14 views
5

consideran este código,¿En qué instancia de delegado de clase se invoca?

public class A 
{ 
    //... 
    void f() 
    { 
      B b = new B(); 
      b.SomeEvent += this.SomeMethod; 
    } 
    void SomeMethod() {} 
} 

public class B 
{ 
    //... 

    public event SomeEventHandler SomeEvent; 

    void h() 
    { 
      if (SomeEvent != null) 
      { 
       SomeEvent.invoke(); 
      } 
    } 
} 

En este fragmento de código, SomeEvent.invoke() invoca realmente SomeMethod() de clase A. Así que en este punto, tengo algunas preguntas:

  • En qué instancia de A, SomeMethod se invoca? ¿Cómo sabe B la instancia en la que se invocará el delegado? ¿Cómo funciona CLR aquí?
  • Además, SomeMethod es un método privado, entonces ¿cómo es que B es capaz de invocar a este método desde fuera de la clase A?

EDIT:

Después de leer las primeras respuestas, vine a saber que tiene una propiedad DelegateTarget delegado en el que se invoca. Pero no podía entender exactamente en qué paso se establece esta propiedad Target? ¿Quién lo configuró? Cuando escribo b.SomeEvent += this.SomeMethod;, ¿establece la propiedad Target también? ¿Cómo exactamente?

Respuesta

2
b.SomeEvent += this.SomeMethod 

Aquí hay una gran cantidad de azúcar que le impide ver lo que realmente está sucediendo. Escrito a cabo, se parece a esto:

b.SomeEvent.add(new MulticastDelegate(this, SomeMethod));  // not legal code 

Dónde add() es el descriptor de acceso complemento para el evento, un compilador genera automáticamente cuando no se declara su propia forma explícita. El primer argumento para el constructor de delegado es la instancia de objeto sobre la que pregunta, la propiedad Target del objeto delegado. Tenga en cuenta que esto tiene efectos secundarios, la suscripción al evento guarda una referencia a su objeto b. Lo cual impide que obtenga basura recolectada, eso sería bastante malo cuando se invoca el evento.

Eso también puede ser un problema, puede filtrar involuntariamente la referencia del objeto. No hay una buena manera en su código de quitar la suscripción del controlador de eventos para que el objeto A viva tanto tiempo como el objeto B al que llamó h().

+0

Finalmente una publicación ... esto me dice algo que estaba buscando. +1 – Nawaz

1
  • Cualquiera que sea ejemplo fue utilizado para la conexión con el evento
  • Debido A aprobó una representación delegada a él fuera de la clase.

Una instancia particular de Delegate tiene una propiedad Target; esto representa la instancia que se utilizará al invocar al delegado.

2

El delegado contiene la referencia de destino para invocar el método. Puede examinar esto con la propiedad Delegate.Target. En este caso, se invocará en la instancia en la que se invoca f. (Es nulo si llama a un método estático.)

En cuanto a la privacidad, esa es solo una de las características de los delegados. Solo puede crear el delegado dentro del código que tiene acceso a un método privado, pero puede ejecutar en cualquier lugar. Piense en esto como si se tratara de implementar una interfaz simplemente llamando a un método privado desde la implementación de la interfaz pública.

+0

Jon: He editado mi pregunta. Por favor mira el EDIT. Quiero entenderlo en profundidad. – Nawaz

+0

Por cierto, compré tu libro, probablemente recuerdes que te lo había dicho cuando lo pedí. Entonces, si usted ha discutido esto en su libro, por favor dígame el capítulo/sección para que lo lea yo mismo, en detalle. – Nawaz

+0

@Nawaz: el Capítulo 2 contiene bastante sobre delegados, sí. Disfrutar :) –

2

¿En qué instancia de A, SomeMethod se invoca? ¿Cómo sabe B la instancia en la que se invocará el delegado? ¿Cómo funciona CLR aquí?

El delegado en realidad contiene una referencia a la instancia real. Esto hará que invoque en la instancia específica en la que se llamó.

Además, SomeMethod es un método privado, entonces ¿por qué B puede invocar este método desde fuera de la clase A?

No ejecuta el método directo - que ejecuta el delegado .Aquí hay una diferencia: la restricción privada solo se aplica al método, pero como la clase en sí crea el delegado, tiene acceso al método, por lo que todo funciona bien.

Cuestiones relacionadas