Java defines the scope of a local variable to be "the rest of the block
in which the declaration appears". The variable declaration is 'hoisted' to the top of the scope, which is defined as where the variable declaration is. Tautological! The rest of your example then falls out the fact local variables can shadow member variables [1].
C# scopes local variables more similarly to javascript's "let".
class Example {
public void Foo() {
Console.WriteLine(f); // Error: The name 'f' does not exist in the current context
}
public void Bar() {
Console.WriteLine(f); // Error: Cannot use local variable 'f' before it is declared
String f = "a";
}
}
In Bar, it knows about the variable f, evidenced by the fact the error message is different to Foo. In Javascript terminology, f was 'hoisted' to the top of Bar. In regular terminology, f is in the lexical scope created by Bar.
[1] Local variables can only shadow member variables, not other local variables. The justification the specification gives for shadowing is so that superclasses can introduce protected member variables without forcing subclasses to rename their local variables. You can still reference the member variable using "this.memberVariable".
C# scopes local variables more similarly to javascript's "let".
In Bar, it knows about the variable f, evidenced by the fact the error message is different to Foo. In Javascript terminology, f was 'hoisted' to the top of Bar. In regular terminology, f is in the lexical scope created by Bar.[1] Local variables can only shadow member variables, not other local variables. The justification the specification gives for shadowing is so that superclasses can introduce protected member variables without forcing subclasses to rename their local variables. You can still reference the member variable using "this.memberVariable".