2012-04-05 22 views
11

soy un poco nuevo en C#, así que se me ocurrió este problema. Pregunta: ¿por qué se llama func2? oh, y una cosa más. Digamos que agrego una función a un delegado. En esta función, llamo a otro delegado; sin embargo, quiero asegurarme de que todas las demás funciones añadidas al primer delegado se invoquen antes de que esta función llame a este delegado, ¿hay alguna solución limpia (que realmente no esté interesada en getInvocationList)? Gracias chicos, eres el mejor.delegado C# no funciona como debería?

class Program 
{ 
    delegate void voidEvent(); 
    voidEvent test; 

    private void func1() 
    { 
     Console.Write("func1"); 
     test -= func2; 
    } 

    private void func2() 
    { 
     Console.WriteLine("func2"); 
    } 

    static void Main(string[] args) 
    { 
     Program p = new Program(); 
     p.test += p.func1; 
     p.test += p.func2; 
     p.test(); 
    } 
} 

Respuesta

21

Cada vez que cambie un delegado (+ = o - =), que está creando efectivamente toda una copia de la lista de invocación (los métodos que se llamará).

Por eso, cuando llame al p.test();, invocará a cada delegado en la lista de invocación en ese momento. Cambiar esto dentro de uno de esos controladores lo cambiará para la próxima llamada, pero no cambiará la llamada que se está ejecutando actualmente.

+3

+1. Sí. Es por eso que puedes escribir 'var func = p.test; if (func! = null) {func(); } 'en escenarios de subprocesamiento múltiple sin bloquear nada. Porque 'func' es una copia de' p.test' y no le importan los cambios realizados en 'p.test'. –

+0

pero después de que llamo test- = func2 y llamo getinvocationlist puedo ver que func2 ya no está en la lista. Entonces, ¿está diciendo que cada delegado tiene dos listas, una que se está invocando actualmente (y no es accesible) y otra que se invocará la próxima vez? – Yamcha

+0

@ user1316459, realmente no tiene dos listas. Pero cuando invoca a un delegado de un archivo, efectivamente dice algo como: "tome el valor del campo * ahora mismo" y luego invoque eso ". Eso significa que está invocando una copia del valor de 'test', no' test' en sí. – svick

8

Reed es, por supuesto, correcto. Aquí hay otra manera de pensar sobre eso.

class Number 
{ 
    public static Number test; 
    private int x; 
    public Number(int x) { this.x = x; } 
    public Number AddOne() 
    { 
     return new Number(x + 1); 
    } 
    public void DoIt() 
    { 
     Console.WriteLine(x); 
     test = test.AddOne(); 
     Console.WriteLine(x); 
    } 
    public static void Main() 
    { 
     test = new Number(1); 
     test.DoIt(); 
    } 
} 

¿Debería imprimir 1, 1 o 1, 2? ¿Por qué?

Debe imprimir 1, 1. Cuando dice

test.DoIt(); 

eso no significa que

 Console.WriteLine(test.x); 
     test = test.AddOne(); 
     Console.WriteLine(test.x); 

! Más bien, lo que significa

Number temporary = test; 
Console.WriteLine(temporary.x); 
test = test.AddOne(); 
Console.WriteLine(temporary.x); 

Cambiar el valor de testno cambia el valor de this en DoIt.

Estás haciendo exactamente lo mismo. Cambiar el valor de test no cambia la lista de funciones que invoca; solicitó una lista particular de funciones para invocar y esa lista se invocará. No puede cambiarlo a la mitad, como tampoco puede cambiar el significado de this a la mitad de una llamada a un método.

+1

Parece que le falta el campo 'x' en su definición de' Número'. – kvb

Cuestiones relacionadas