Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I return a reference to new object instance from a C# delegate?

I'm learning/experimenting with some functional patterns within C# and I've hit a bump I can't quite explain. I'm sure it's a simple answer (I hope) but I'm struggling to see it. Likely has to do with closures, etc and my inability to get out-of-box is hiding the answer from me!

Here's my experiment: I'm trying to return a brand new instance of a particular class from within a function delegate..

public class Foo{
    string A { get; set ; }
}

static void Main( string[] args ){
    // the delegate...
    Func<Foo,bool> someFunc = o => {
        o = new Foo { A = "A new instance of o?" };
        return true;
    };

    Foo foo = null;   // was hoping to replace this via delegate
    var myFunc = someFunc;
    var result = myFunc( foo );

    if ( foo == null )
        Console.WriteLine( "foo unchanged :-(" );
    else
        Console.WriteLine( foo.A ); // hoping for 'A new instance of o?'

Of course, I just get "foo unchanged :-(" in my output. I made a slight variation on the test where I passed in a non-null Foo instance and modified the property "A" (vs returning a new instance) and that worked okay (that is, I can mutate an existing object just like I would expect when passing object references to functions) I just can't seem to get a new instance out of my delegate.

So? Am I just doing something wrong in the code? Can this be done at all? Would love to understand why this doesn't work.

like image 442
robcom88 Avatar asked Mar 17 '26 17:03

robcom88


1 Answers

Formal parameter o is a copy of the value of foo; mutating o does not mutate foo. It's the same as when you say:

int x = 1;
int y = x;
y = 2;

That doesn't change x. y is a copy of the value of x, not an alias to x.

You're overthinking the problem. If you want to have a delegate that mutates a local then just write a delegate that mutates a local:

Foo foo = null;   // was hoping to replace this via delegate
Action mutateFoo = () => { foo = new Foo() { A = "whatever"}; };
mutateFoo();
if ( foo == null )
    Console.WriteLine( "foo unchanged :-(" );
else
    Console.WriteLine( foo.A );

If all you want to do is mutate a variable then mutate the variable. There's no need to pass anything in or out from the delegate if you just want to perform a side effect.

I notice that you said that you were experimenting with functional patterns. Remember, functional programming discourages variable mutation, so you might be going down a false path here.

like image 116
Eric Lippert Avatar answered Mar 19 '26 06:03

Eric Lippert



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!