What I am showing below, is rather a theoretical question. But I am interested in how the new C#7 compiler works and resolves local functions.
In C#7
Parameters and local variables from the enclosing scope are available inside a local function.
I thought, each inner Main() would have a local scope and is hidden outside.
C# does not overwrite names from the parent scope, so there is and ambiguity for the local name Main
which defined in current and parent scopes.
So in the second example both declaration of void Main()
are available for the inner scope and compiler shows you an error.
Here is an example with variables and local functions
which could help you to see the problem in the familiar environment. To make it clear that it is only matter of scope I modified example and added functions to variables to make it clear:
class Test
{
int MainVar = 0;
public void Main()
{
if (this.MainVar++ > 10) return;
int MainVar = 10;
Console.WriteLine($"Instance Main, this.MainVar=${this.MainVar}, MainVar={MainVar}");
void Main()
{
if (MainVar++ > 14) return;
Console.WriteLine($"Local Main, this.MainVar=${this.MainVar}, MainVar={MainVar}");
// Here is a recursion you were looking for, in Example 1
this.Main();
// Let's try some errors!
int MainVar = 110; /* Error! Local MainVar is already declared in a parent scope.
// Error CS0136 A local or parameter named 'MainVar' cannot be declared in this scope
// because that name is used in an enclosing local scope to define a local or parameter */
void Main() { } /* Error! The same problem with Main available on the parent scope.
// Error CS0136 A local or parameter named 'Main' cannot be declared in this scope
// because that name is used in an enclosing local scope to define a local or parameter */
}
Main(); // Local Main()
this.Main(); // Instance Main()
// You can have another instance method with a different parameters
this.Main(99);
// But you can't have a local function with the same name and parameters do not matter
void Main(int y) { } // Error! Error CS0128 A local variable or function named 'Main' is already defined in this scope
}
void Main(int x)
{
Console.WriteLine($"Another Main but with a different parameter x={x}");
}
}
There are even the same errors when you try to overwrite local variable and local function.
So as you can see it is a matter of scopes and you cannot overwrite local function or variable.
BTW, in a first example you could make recursive call by using this.Main();
:
void Main()
{
void Main()
{
Console.WriteLine("Hello!");
}
this.Main(); // call instance method
}
Footnote: Local functions are not represented as delegates as some commentators suggest and it makes local functions
much leaner in both memory and CPU.