Рассмотрите этот фрагмент кода и попытайтесь угадать, что y1
и y2
оценивают как
static class Extensions
{
public static Func<T> AsDelegate<T>(this T value)
{
return () => value;
}
}
class Program
{
static void Main(string[] args)
{
new Program();
}
Program()
{
double x = Math.PI;
Func<double> ff = x.AsDelegate();
Func<double> fg = () => x;
x = -Math.PI;
double y1 = ff(); // y1 = 3.141..
double y2 = fg(); // y2 = -3.141..
}
}
Можно сказать, -Aha- double - это тип значения, поэтому значение, возвращаемое методом расширения копия основной x
.Но когда вы изменяете вышеупомянутое на делегатов классов, результаты все еще различны.Пример:
class Foo
{
public double x;
}
Program()
{
Foo foo = new Foo() { x=1.0 };
Func<Foo> ff = foo.AsDelegate();
Func<Foo> fg = () => foo;
foo = new Foo() { x = -1.0 };
double y1 = ff().x; // y1 = 1.0
double y2 = fg().x; // y2 = -1.0
}
Таким образом, две функции должны возвращать два разных экземпляра одного и того же класса.Интересно учитывать, что ff()
содержит ссылку на локальную переменную foo
, а fg()
- нет, и это зависит от того, что находится в области видимости в настоящее время.
Так что же происходит, когда эти два делегатапередаются другим частям кода, которые не видны экземпляру foo
?Почему-то вопрос о том, кому принадлежит какая информация (данные) становится все менее и менее понятным, когда методы расширения объединяются с делегатами.