I wrote some code recently where I unintentionally reused a variable name as a parameter of an action declared within a function that already has a variable of the same name. For example:
var x = 1; Action<int> myAction = (x) => { Console.WriteLine(x); };
When I spotted the duplication, I was surprised to see that the code compiled and ran perfectly, which is not behavior I would expect based on what I know about scope in C#. Some quick Googling turned up SO questions that complain that similar code does produce an error, such as Lambda Scope Clarification. (I pasted that sample code into my IDE to see if it would run, just to make sure; it runs perfectly.) Additionally, when I enter the Rename dialog in Visual Studio, the first x
is highlighted as a name conflict.
Why does this code work? I'm using C# 8 with Visual Studio 2019.
Do not use the same variable name in two scopes where one scope is contained in another. For example, No other variable should share the name of a global variable if the other variable is in a subscope of the global variable.
We know every Child class inherits variables and methods (state and behavior) from its Parent class. Imagine if Java allows variable overriding and we change the type of a variable from int to Object in the Child class.
You can access a parent's protected or private variables if those variables are declared as static . Without the static keyword, you'll need a reference to an instance of the class, instead of a static reference to the class itself.
You can reuse some variables depending on their data types, but whether or not you should reuse a variable depends on what you're doing. Your code can work, but you're declaring i a second time which is incorrect as it already exists with a value of 0.
Why does this code work? I'm using C# 8 with Visual Studio 2019.
You've answered your own question! It's because you're using C# 8.
The rule from C# 1 through 7 was: a simple name cannot be used to mean two different things in the same local scope. (The actual rule was slightly more complex than that but describing how is tedious; see the C# specification for details.)
The intention of this rule was to prevent the sort of situation that you're talking about in your example, where it becomes very easy to be confused about the meaning of the local. In particular, this rule was designed to prevent confusions like:
class C { int x; void M() { x = 123; if (whatever) { int x = 356; ...
And now we have a situation where inside the body of M
, x
means both this.x
and the local x
.
Though well-intentioned, there were a number of problems with this rule:
I made an effort in the Roslyn rewrite to sort this out; I added some new error messages, and made the old ones consistent regarding where the error was reported. However, this effort was too little, too late.
The C# team decided for C# 8 that the whole rule was causing more confusion than it was preventing, and the rule was retired from the language. (Thanks Jonathon Chase for determining when the retirement happened.)
If you are interested to learn the history of this problem and how I attempted to fix it, see these articles I wrote about it:
https://ericlippert.com/2009/11/02/simple-names-are-not-so-simple/
https://ericlippert.com/2009/11/05/simple-names-are-not-so-simple-part-two/
https://ericlippert.com/2014/09/25/confusing-errors-for-a-confusing-feature-part-one/
https://ericlippert.com/2014/09/29/confusing-errors-for-a-confusing-feature-part-two/
https://ericlippert.com/2014/10/03/confusing-errors-for-a-confusing-feature-part-three/
At the end of part three I noted that there was also an interaction between this feature and the "Color Color" feature -- that is, the feature that allows:
class C { Color Color { get; set; } void M() { Color = Color.Red; } }
Here we have used the simple name Color
to refer to both this.Color
and the enumerated type Color
; according to a strict reading of the specification this should be an error, but in this case the spec was wrong and the intention was to allow it, as this code is unambiguous and it would be vexing to make the developer change it.
I never did write that article describing all the weird interactions between these two rules, and it would be a bit pointless to do so now!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With