-1

If I had this code:

public virtual void Foo()
{
    void Bar()
    {
        // do important stuff for Foo
    }
}

// In a child class: 
public override void Foo()
{
    Bar();        // Doesn't work
    base.Bar();   // Also doesn't work
}

Is there anyway to call the local function defined in Bar inside of Foo without making Bar a normal method?

AustinWBryan
  • 3,249
  • 3
  • 24
  • 42
  • 7
    It's literally the purpose of making a method a local method that it's not accessible outside of that method. If you want it accessible outside of that method, then *don't make it a local method*. – Servy Aug 16 '18 at 21:22
  • no they are created as private not protected members, [see also here](https://stackoverflow.com/q/45337983/1132334), and are not in scope anywhere outside the containing method. – Cee McSharpface Aug 16 '18 at 21:24
  • @Servy That was my hunch, just wanted to be sure. Thanks – AustinWBryan Aug 16 '18 at 21:27
  • If you have a realistic example of *why* you want to do this, there may be some pattern out there designed to solve the problem you're facing. – Rufus L Aug 16 '18 at 21:45
  • The problem was I had a few lines in the `Start` method that's called on the creation by Unity, that setup the object and then called a method that would do something else. I wanted to have the setup be refactored into a different local function, and then have the base call that local function to do the setup, but then not call the other method until later on. I got what I wanted by using a boolean though and the child class sets the boolean `isActive` to `false` then calls the base `Start` method. – AustinWBryan Aug 16 '18 at 21:50

2 Answers2

4

Is there anyway to call the local function defined in Bar inside of Foo without making Bar a normal method?

There is no by-design way. That's what "local" means. A local is accessible by name only by code in the location of the declaration; that's why they're called "locals".

Is there "any" way? Sure, you could do all kinds of shenanigans with reflection and decompilation and unsafe code and so on. Please don't. Those are implementation details of the compiler; don't try to reverse-engineer them and certainly do not rely on any implementation choice the compiler team has made being permanent!

Eric Lippert
  • 647,829
  • 179
  • 1,238
  • 2,067
  • You're right, if they did allow it, it wouldn't be consistent with the fact that overriding methods can't see local variables – AustinWBryan Aug 16 '18 at 21:52
-1

Yes, you can pass around a delegate to it just as you do with any lambda expression. And no, this doesn't break any "rules," and we do it in Javascript all the time, under the module pattern, or whatever it's called.

public class MyBase
{
    protected Action Foo()
    {
        return Local;

        void Local()
        {
            Console.WriteLine("Hello world");
        }
    }
}

public class MyDerived : MyBase
{
    public void HelloWorld()
    {
        var f = Foo();
        f();
    }
}


public class Program
{
    public static void Main()
    {
        var o = new MyDerived();
        o.HelloWorld();
    }
}

Output:

Hello world

Link to DotNetFiddle

John Wu
  • 50,556
  • 8
  • 44
  • 80
  • Though this is certainly true, I understood the question to mean "without modifying the base class". Your solution involves modifying the base class; if you're going to do that, then you might as well just make it a non-local protected method in the first place, rather than passing it around as a delegate! – Eric Lippert Aug 16 '18 at 21:55
  • Maybe. I don't know, I'm thinking there may be a case where you want to protect `local` from modification but not invocation. If you just make it protected, someone could override it. I admittedly haven't thought it through, and you could be right. But the point is, it is "possible" in some fashion. – John Wu Aug 16 '18 at 22:00
  • 1
    @JohnWu It can only be overridden if you make it virtual. The only difference between this and a method is that it's way more complex to the programmer, and probably performs worse. Other than that there's no behavioral difference. – Servy Aug 16 '18 at 22:01
  • There are some important differences. For example, a local function can close around a local variable. A delegate to a local function can only be created by the method containing the local. So it's a different type of scope control. It has many of the features of a lambda expression, but with a more verbose and meaningful declaration, and the ability to infer its type. I'd like to remain open-minded that there may be some use for it, to someone. – John Wu Aug 16 '18 at 23:20
  • But you've created method that does nothing but return a delegate to a local. There's no local variables to capture here. I'm not arguing that local method are pointless, I'm arguing that you creating a new method for the sole purpose of returning a delegate to a local method, is pointless, because you have no means by which to actually leverage the useful features of a local method. – Servy Aug 17 '18 at 13:57
  • It's a hello world program. Of course it's pointless. The code example is meant to demonstrate a concept, not solve a business problem, or show every possibility. I think the issue here is that we have a solution is search of a problem, which is never a good idea. But the point is... solutions of this kind are possible, whatever the problem might be. – John Wu Aug 17 '18 at 14:57