Search code examples
c#anonymous-methods

Do anonymous methods passed to actions obtain data by value or reference?


I am creating an anonymous method and passing it into an action to be invoked later on. I would like to pass some numeric data (int) into my anonymous method. In order to pass the data by value, am I required to create copies? Or, will the data be passed by value?

Here is what I think the implementation would look like, if I had to create copies:

private void CreateAction()
{
    int bus = 4;
    CustomObject[] data = new object[16];
    int length = 1500;

    this.doWorkLater = new Action(() =>
    {
        var busCopy = bus;
        var dataCopy = data;
        var lengthCopy = length;

        this.WorkMethod(busCopy, dataCopy, lengthCopy);
    });
}

Is this (the above code) necessary in order to get length and bus by value?

In this case, will CustomObject[] data (some class I have created) be passed by reference or by value?


Solution

  • What you pass is not a By-Value Copy.

    If you're not going to modify the values before executing the action, then you don't need to worry about how you pass the values. But no they are no passed by value. Even if you return the action and Invoke it from another method. the values are persisted in a class generated by the compiler. No need to worry about that

    If you expect the data to change before executing the action then you're doing it wrong. The approach you're using (Copy a Value-Type to a local variable) should be done outside the action and not inside of it. As for the reference type (Array) even if you copy it to a local variable, the reference it copied so any change in the copy local variable is reflected.

    private void CreateAction()
    {
        int bus = 4;
        CustomObject[] data = new object[16];
        int length = 1500;
    
        var busCopy = bus; // a copy of bus
        var dataCopy = data; // reference copy
        var lengthCopy = length; // a copy of length
    
        this.doWorkLater = new Action(() =>
        {
            this.WorkMethod(busCopy, dataCopy, lengthCopy);
        });
    
        bus = 10; // No effect on the action
        length = 1700; // No effect on the action
    
        this.doWorkLater();
    }
    

    This looks pointless, but you may sometimes need to copy a local variable to another local variable before passing it to an anonymous method. Check this Valid Example that fixes a reported unexpected behavior !