-1

I'd like to write a method that takes a string parameter -- say, sLastName -- and returns a very simple Func<string> that has captured that variable and simply returns it. This doesn't work...

Func<string> MyMethod (string myStringVar)
{
    return () => myStringVar;
}

...in that if sLastName is "Smith", and I call MyMethod(sLastName).Invoke(), I'll get back "Smith"; but if I then set sLastName to "Jones" and call MyMethod again, I'll still get back "Smith".

So, to make using MyMethod as simple as possible, I'd like to be able to pass sLastName in as a string, and then (assuming sLastName has been declared, is in scope, etc.), by somehow leveraging the Expression class, return a Func<string> with sLastName embedded as a captured variable... like so...

MyMethod("sLastName").Invoke()

...and it would return the current value of sLastName. But I can't see any way of using strings to build Expressions, and haven't yet found such in StackOverflow. Any way to do this?

Thanks in advance! (By the way, I know I can just create the lambda on the fly and pass it in as a parameter; just looking for something even simpler, where I can use only the name of the variable.)

Dave
  • 1
  • 4
    The real question is what do you need this for? – Alejandro Aug 10 '21 at 21:08
  • No, you [cannot](https://stackoverflow.com/a/9183090/11683) access a *local variable* by its string name. The `Func f = () => sLastName` is the simplest you will get. – GSerg Aug 10 '21 at 21:26
  • 2
    "(assuming sLastName has been declared, is in scope, etc.)": if it's a local variable, it won't _ever_ be in scope for `MyMethod`. If it's a field on the same object as `MyMethod`, then you could use reflection. It still seems really weird. Worth questioning why. – StriplingWarrior Aug 10 '21 at 21:59
  • 1
    I don't believe this is a real question. – David L Aug 10 '21 at 22:01
  • Have you tried to make a copy of `myStringVar` into a local variable to capture the copy instead of a reference to the original string? In C# capture by reference or value is not explicit as in C++. – Phil1970 Aug 10 '21 at 22:13
  • Could you post a more full code example of what you're trying to achieve so that the usage is clear? – mheskamp Aug 11 '21 at 20:57
  • @Alejandro... well, that may be *your* real question, but it's not mine ;-) Mine was pretty much just what was stated: Any way to do this? MyMethod("sLastName").Invoke(); – Dave Aug 12 '21 at 03:24
  • @GSerg... Thank you, I'm pretty sure you've answered the question correctly, and comprehensively at that, I was pretty much guessing that was the case... but I never found any sort of authoritative, definitive statement of it. It seems like not only is there "no support for it," but they're really trying to avoid that dynamic security hole at all costs. – Dave Aug 12 '21 at 03:28
  • @DavidL... I don't believe yours is a real answer... we're even! – Dave Aug 12 '21 at 03:32
  • @Dave It's not a matter of whose question is. This post looks very much like an[XY problem](https://xyproblem.info/) (you got a problem, think of a solution that didn't work and ask about that instead of asking about your initial problem). By knowing the reason behind the question we can better direct you if the case is that a completely different approach is prefereable. – Alejandro Aug 12 '21 at 13:36
  • @Alejandro... Well, thank you, but my answer to you was rather tongue-in-cheek, to be honest, because I see an awful lot of that type of second-guessing on SO, and, no offense, but I'm not a fan. What I wanted was what I asked for, a syntactically and operationally simpler way to do an assignment like that. What I'd really been hoping was that in the rather rich Expression class, there'd be some way of wangling it, but I guess not. Thanks again, in any case! – Dave Aug 13 '21 at 14:26

1 Answers1

-1

What you really want is for myStringVar to be declared as a ref variable in MyMethod so that it's passed by reference instead of by value (which will copy the value and is why you don't see the updated value). That way the lamda has a reference to myStringVar and will thus return the latest value whenever called. However, ref variables aren't allowed to be referenced in lambda functions.

In your code, you're passing by value:

Func<string> MyMethod (string myStringVar)
{
    return () => myStringVar; // When MyMethod is called, the value of myStringVar inside this function and thus the lambda is a copy of what was passed in
}

This would be similar, but without knowing what you're trying to accomplish I'm not sure if it will work for your scenario:

public static void Main()
{
    var myStringVar = "Smith";
            
    Func<string> returnMyString = () => MyMethod(ref myStringVar);
        
    Console.WriteLine(returnMyString());
    
    myStringVar = "Jones";
    Console.WriteLine(returnMyString());
}

public static string MyMethod(ref string myStringVar)
{
    return myStringVar; // myStringVar holds a reference to the one from the Main program and so returns the latest value
}

The output is: Smith Jones

Here's a .net fiddle with the example

mheskamp
  • 74
  • 6
  • The `Func returnMyString = () => MyMethod(ref myStringVar);` at the original method level is exactly what the OP is trying to avoid. If it was okay to have that at the original method level, then `Func returnMyString = () => myStringVar` would be much simpler. – GSerg Aug 11 '21 at 19:00
  • Yes that's true...a full code example in the OP would be helpful because the exact usage wasn't clear. The main point I wanted to make was about passing by reference vs. passing by value because that understanding seems to be the heart of the issue and it doesn't work with lambdas – mheskamp Aug 11 '21 at 20:56
  • @GSerg, correct, but thank you both for your assistance! – Dave Aug 12 '21 at 03:29