Причина в наступному:
Те, як ви оголошуєте делегата, вказує безпосередньо на ToStringметод статичного екземпляра int. Він захоплюється під час створення.
Як зазначає flindeberg у коментарях нижче, кожен делегат має ціль та метод, який слід виконати на цілі.
У цьому випадку метод, який слід виконати, очевидно є ToStringметодом. Цікавою частиною є екземпляр, на якому виконується метод: це екземпляр Iна момент створення, тобто делегат не використовує, Iщоб змусити екземпляр використовувати, але він зберігає посилання на сам екземпляр.
Пізніше ви змінюєте Iінше значення, в основному призначаючи йому новий екземпляр. Це магічним чином не змінює екземпляр, захоплений вашим делегатом, навіщо це робити?
Щоб отримати очікуваний результат, вам слід змінити делегата на такий:
static Func<string> del = new Func<string>(() => I.ToString());
Подібно до цього, делегат вказує на анонімний метод, який виконується ToStringна поточному Iна момент виконання делегата.
У цьому випадку виконуваний метод - це анонімний метод, створений у класі, в якому оголошено делегат. Екземпляр є нульовим, оскільки це статичний метод.
Погляньте на код, який компілятор створює для другої версії делегата:
private static Func<string> del = new Func<string>(UserQuery.<.cctor>b__0);
private static string cctor>b__0()
{
return UserQuery.I.ToString();
}
Як бачите, це звичайний метод, який щось робить . У нашому випадку він повертає результат виклику ToStringпоточного екземпляра I.