Использование делегатов в C#
в языке C# и .NET framework, не могли бы вы помочь мне с пониманием делегатов? Я пытался проверить какой-то код, и обнаружил, что результаты, которые я получил, были неожиданными для меня. Вот это:
class Program
{
public static int I = 0;
static Func<string> del = new Func<string>(I.ToString);
static void Main(string[] args)
{
I = 10;
Console.WriteLine("{0}", del());
}
}
ответ был 0, но не 10. Зачем?
5 ответов:
причина заключается в следующем:
способ объявления делегата он указывает непосредственно на
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
.
вам нужно пройти в
I
функции, так чтоI.ToString()
может быть выполнено в надлежащее время (а не в момент создания функции).class Program { public static int I = 0; static Func<int, string> del = num => num.ToString(); static void Main(string[] args) { I = 10; Console.WriteLine("{0}", del(I)); } }
вот как это должно быть сделано:
using System; namespace ConsoleApplication1 { class Program { public static int I = 0; static Func<string> del = new Func<string>(() => { return I.ToString(); }); static void Main(string[] args) { I = 10; Console.WriteLine("{0}", del()); } } }
делегат C# позволяет инкапсулировать как объект, так и экземпляр и метод. Объявление делегата определяет класс, производный от класса System.Делегат. Экземпляр делегата инкапсулирует список вызовов, который представляет собой список одного или нескольких методов, каждый из которых называется вызываемой сущностью.
узнайте больше формы
http://asp-net-by-parijat.blogspot.in/2015/08/what-is-delegates-in-c-how-to-declare.html