Using delegates in C#

情到浓时终转凉″ 提交于 2019-12-20 08:09:20

问题


In C# language and .NET framework, could you help me with understanding delegates? I was trying to check some code, and found that the results I received were unexpected for me. Here it is:

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());
    }
}

The answer was 0, but not 10. Why?


回答1:


The reason is the following:

The way you declare the delegate it points directly to the ToString method of the static int instance. It is captured at the time of creation.

As flindeberg points out in the comments below, each delegate has a target and a method to be executed on the target.

In this case, the method to be executed is obviously the ToString method. The interesting part is the instance the method is executed on: It is the instance of I at the time of the creation, meaning that the delegate is not using I to get the instance to use but it stores the reference to the instance itself.

Later you change I to a different value, basically assigning it a new instance. This doesn't magically change the instance captured in your delegate, why should it?

To get the result you expect, you would need to change the delegate to this:

static Func<string> del = new Func<string>(() => I.ToString());

Like this, the delegate points to an anonymous method that executes ToString on the current I at the time of the execution of the delegate.

In this case, the method to be executed is an anonymous method created in the class in which the delegate is declared in. The instance is null as it is a static method.

Have a look at the code the compiler generates for the second version of the delegate:

private static Func<string> del = new Func<string>(UserQuery.<.cctor>b__0);
private static string cctor>b__0()
{
    return UserQuery.I.ToString();
}

As you can see, it is a normal method that does something. In our case it returns the result of calling ToString on the current instance of I.




回答2:


You need to pass in I to your function so that I.ToString() can be executed at the appropriate time (instead of at the time function is created).

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));
    }
}



回答3:


Here is how this should be done:

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());
        }
    }
}



回答4:


C# delegate enable encapsulate both an object and instance and a method. A delegate declaration defines a class that is derived from the class System.Delegate. A delegate instance encapsulates an invocations list, which is a list one or more method, each of which is referred to as callable entity.

learn more form

http://asp-net-by-parijat.blogspot.in/2015/08/what-is-delegates-in-c-how-to-declare.html




回答5:


My guess is because int are passed by values not references, and for that reason when creating the delegate, it's a delegate to the method ToString of the current value of "I" (0).



来源:https://stackoverflow.com/questions/13603795/using-delegates-in-c-sharp

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!