La razón es la siguiente:
La forma en que declara el delegado apunta directamente al ToString
método de la instancia int estática. Se captura en el momento de la creación.
Como señala flindeberg en los comentarios a continuación, cada delegado tiene un objetivo y un método para ejecutar en el objetivo.
En este caso, el método a ejecutar es obviamente el ToString
método. La parte interesante es la instancia en la que se ejecuta el método: es la instancia de I
en el momento de la creación, lo que significa que el delegado no está usando I
para que la instancia se use, sino que almacena la referencia a la instancia en sí.
Más tarde, cambia I
a un valor diferente, básicamente asignándole una nueva instancia. Esto no cambia mágicamente la instancia capturada en su delegado, ¿por qué debería hacerlo?
Para obtener el resultado que espera, deberá cambiar el delegado a esto:
static Func<string> del = new Func<string>(() => I.ToString());
Así, el delegado apunta a un método anónimo que se ejecuta ToString
en la corriente I
en el momento de la ejecución del delegado.
En este caso, el método a ejecutar es un método anónimo creado en la clase en la que se declara el delegado. La instancia es nula ya que es un método estático.
Eche un vistazo al código que genera el compilador para la segunda versión del delegado:
private static Func<string> del = new Func<string>(UserQuery.<.cctor>b__0);
private static string cctor>b__0()
{
return UserQuery.I.ToString();
}
Como puede ver, es un método normal que hace algo . En nuestro caso, devuelve el resultado de llamar ToString
a la instancia actual de I
.