Причина в следующем:
То, как вы объявляете делегат, указывает непосредственно на ToString
метод статического экземпляра int. Он зафиксирован во время создания.
Как указывает Флиндеберг в комментариях ниже, у каждого делегата есть цель и метод, который должен выполняться на цели.
В этом случае очевидно, что выполняемый ToString
метод - это метод. Интересной частью является экземпляр, на котором выполняется метод: это экземпляр I
во время создания, а это означает, что делегат не использует I
экземпляр для использования, но сохраняет ссылку на сам экземпляр.
Позже вы измените I
значение, присвоив ему новый экземпляр. Это не меняет волшебным образом экземпляр, захваченный в вашем делегате, зачем это нужно?
Чтобы получить ожидаемый результат, вам нужно будет изменить делегата на это:
static Func<string> del = new Func<string>(() => I.ToString());
Таким образом, делегат указывает на анонимный метод, который выполняется ToString
в текущем состоянии I
во время выполнения делегата.
В этом случае выполняемый метод - это анонимный метод, созданный в классе, в котором объявлен делегат. Экземпляр имеет значение null, поскольку это статический метод.
Взгляните на код, который компилятор генерирует для второй версии делегата:
private static Func<string> del = new Func<string>(UserQuery.<.cctor>b__0);
private static string cctor>b__0()
{
return UserQuery.I.ToString();
}
Как видите, это нормальный метод, который что- то делает . В нашем случае он возвращает результат вызова ToString
текущего экземпляра I
.