Search code examples
c#lambdaanonymous-functionencapsulation

How to make a function private to a method?


I'm working on a method that needs to repeat a small operation at different spots, but the code to be repeated should be private to the method. The obvious solution is a nested function. Whatever I try however, the C# compiler barfs at me.

Something roughly equal to this Perl snippet:

my $method = sub {
    $helper_func = sub { code to encapsulate };

    # more code

    &$helper( called whenever needed );

    # more code
}

is what I am talking about, and what I'm trying to accomplish in C#.

No other method in the class should be able to access the helper function in this context. The most logical means of writing this construct in C#, as it appears to me would be something like this:

var helper = (/* parameter names */) => { /* code to encapsulate */ };

And actually make the compiler earn its keep.

Since such an assignment is forbidden, as is the equivalent using the older delegate(){} syntax in place of the lambda, and so is declaring a delegate type within a method—what csc actually allows me to write however, is this:

private delegate /* return type */ Helper(/* parameters */);
private /* return type */ method(/* parameters */) {

    Helper helper = (/* parameter names */) => { 
        /* code to encapsulate */
    };

    // more code

    helper( /* called whenever needed */ );

    // more code
}

Which is all fine and dandy for not copy and pasting a chunk of code around and editing the parameters by hand but it leaks a private delegate type to the rest of the class rather than keeping it private to the method. Which defeats the purpose in the first place. Using goto statements and local variables for parameters would provide better encapsulation of "helper" in this context without sacrificing code reuse. If I wanted to simulate function calls by passing parameters through registers, I think would rather use an assembler. I haven't found an acceptable way of refactoring the code to avoid the problem altogether either.

So, is it even possible to force this Common Object Oriented Language to obey?


Solution

  • If you are in C# 3.5 or higher you can take advantage of the lambdas and convenience delegate declarations Func<> and Action<>. So for instance

    void DoSomething()
    {
      Func<int,int> addOne = (ii) => ii +1;
      var two = addOne(1);
    }
    

    The reason you can't do

    var addOne = (ii) => ii +1;
    

    is because of Homoiconicity, the lambda can be interpreted as two different constructs, a delegate and an expression tree. Thus the need to be explicit in declaration.