开发者

Problem about Func<string>

开发者 https://www.devze.com 2023-03-14 20:47 出处:网络
class Program { static void Main() { int i = 0; whatever x = new whatever(i); Console.WriteLine(x); i = 1; Console.WriteLine(x);
class Program
{
    static void Main()
    {
        int i = 0;
        whatever x = new whatever(i);
        Console.WriteLine(x);
        i = 1;
        Console.WriteLine(x);
        Console.ReadKey();
    }

    class whatever
    {
       public whatever(object variable)
       {
           this.variable = () => variable.ToString();
       }

       private Func<string> variable;
       public string data;

       public override string ToString()
       {
           开发者_如何学运维data = variable();
           return data;
       }
}

Output:

0
0

what I want to do is get updated i's value.


If you want to capture the local variable then you've put the lambda in the wrong place. The lambda has to go where it can be closed over the outer variable you want to capture.

class Program
{
    static void Main()
    {
        int i = 0;
        var x = new Whatever<int>(()=>i);
        Console.WriteLine(x);
        i = 1;
        Console.WriteLine(x);
        Console.ReadKey();
    }
}

class Whatever<T>
{
   private Func<T> variable;
   public Whatever(Func<T> func)
   {
       this.variable= func;
   }
   public override string ToString()
   {
       return this.variable().ToString();
   }
}

Does that make sense? See, the lambda has to be where the "i" is declared, so that "i" is an outer variable of the lambda and therefore the lambda sees changes to it.


i is an integer (value type), which is passed by value - a copy of the value is passed to the whatever constructor. When you change its value on the Main method, it doesn't change what has been already passed to the class. So you can't get the updated value on whatever.

If you have an object which holds a field of an integer value, and then pass that object to whatever, then changes to that field will be reflected on the class.


Maybe the problem is that delegate is bound to boxed integer data. This is why you change your int and delegate evaluates to old boxed data.

Try it with constructor that takes an int.

But, yes it's true that ints are pased by value, so this will not work. Pass delegate to ctor.

class Program
{
        static void Main()
        {
            int i = 0;
        whatever x = new whatever(() => i.ToString());
        Console.WriteLine(x);
        i = 1;
        Console.WriteLine(x);
        Console.ReadKey();
    }

    class whatever
    {
        public whatever(Func<string> someFunc)
        {
            this.variable = someFunc;
        }

        private Func<string> variable;
        public string data;

        public override string ToString()
        {
            data = variable();
            return data;
        }
    }
 }

Output: 0 1

Or as other have indicated:

class Program
{
    static void Main()
    {
        var myRefType = new MyRefType();
        myRefType.MyInt = 0;

        var x = new whatever(myRefType);
        Console.WriteLine(x);
        myRefType.MyInt = 1;

        Console.WriteLine(x);
        Console.ReadKey();
    }

    class whatever
    {
        public whatever(MyRefType myRefType)
        {
            this.variable = () => myRefType.MyInt.ToString();
        }

        private Func<string> variable;

        public override string ToString()
        {
            return variable();
        }
    }

    class MyRefType
    {
        public int MyInt { get; set; }
    }
}

Outputs: 0 1


Integers are of value type, not reference type.


int is value type, meaning its value is copied each time you use it and not its reference. The best way to make this work is make reference type around int:

class IntRef
{
    public int Val;
}

You will need to always use IntRef.Val and passing the IntVal itself around will retain the reference.

0

精彩评论

暂无评论...
验证码 换一张
取 消