Here is my code in which the identifier problem causes.
for (int i = 0; i < buttons.Length; i++)
{
Text[] = buttons[i].GetComponentsInChildren<Text>();
}
Unknown identifier: This type of error could mean that Unity does not know the variable that you are referring to and it is expecting an Identifier.
This might be due to these reasons:
The name of the variable that you are using is incorrect.
The variable has not been declared yet.
The variable has been declared but outside the scope of the method.
Note: The names of all variables and functions are case-sensitive, just using an incorrect case, will assume that you're referring to another variable.
Try this:
for (int i = 0; i < buttons.Length; i++)
{
Text[] texts = buttons[i].GetComponentsInChildren<Text>();
}
You can refer these links link-1 link-2
Related
public Grid (int width, int height, char defaultCharacter) {
for (int n = 0; n <= height; n++) {
List<char> aRow;
for (int i = 0; i <= width; i++) {
aRow.Add(defaultCharacter);
}
this.grid.Add(aRow);
}
}
This is some of my code.
When I run this on Xamarin Studio it gives me an error on these lines saying "Use of unassigned local variable 'aRow'":
aRow.Add(defaultCharacter);
this.grid.Add(aRow);
This function is in a class called Grid, with one variable:
List<List<char>> grid = new List<List<char>>();
Any ideas on why this variable is unassigned?
The variable that you didn't initialize is aRow. I think an average person knows that it doesn't have a value. So in order to solve this, you should give a value to it.
As you should already know, we use the = operator to give values to variables. So you can instantiate a new instance of List<char> like this:
aRow = new List<char> ();
And you may want to ask why it must have a value before you use it. Because sometimes a variable is null (nothing). Let's imagine what will happen if the value of aRow is null. aRow.Add will cause a NullReferenceException because it is nothing.
If you don't give the variable a value, the compiler doesn't know whether it is null or something else. Thus, it complains.
I faced this strange behavior when I was coding. So I ask it here.
What is the scope of a for loop when declaring variables?
This code compiles fine
for (int i = 0; i < 10; i++) { }
for (int i = 0; i < 10; i++) { }
This means both int i are not in same scope.
But this code does not compile.
for (int i = 0; i < 10; i++) { }
int i; // Conflicts with both first loop and second one.
for (int i = 0; i < 10; i++) { }
This means the int i in middle of loops has the same scope of first loop and the second loop.
But how can int i in two for loops have different scope, but the same scope with middle int i? Because currently I see them at the same level.
I know the second code does not compile. Why does the first code compile then if there is problem in scopes. Is this an exception inside the compiler?
The C# compiler does not check whether a variable was declared before or after another variable. All that matters is the scope. The i variable declared between loops surely conflicts with the second loop, because if you use i inside the loop, there is no way to distinguish which i you'd like to use. As for the first loop, an error is still shown, because the block where i is declared encapsulates also the first loop.
For example, the following will not compile, even though j is not visible outside inner braces, so there should not be any ambiguity regarding i:
{
{
int i = 1;
int j = 1;
}
int i = 0; // compiler error: A local variable i cannot be declared in this scope (...)
// j is not visible here
}
Edit regarding the comment:
Why is the following fine?
{
for(int i = 1; i < 10; i++) {}
for(int i = 1; i < 10; i++) {}
}
When you declare a for loop variable, it is visible only inside the loop block. That means that the scopes of both variables are disjoint, since there is no line of code where one block "overlaps" the other one.
The scope of a for loop, for(INIT; COND; INCR) { BLOCK } is identical in scoping to
{
INIT;
while (COND) {
BLOCK;
INCR;
}
}
Thus a for loop can be best thought of as two nested scopes. (Note: the above conversion from for to while does not properly capture the behavior of continue. However, this question is not focused on that)
The issue you run into with the int i outside of the for loop is something called "shadowing." In C++, if you declared a scoped variable with the same name as something in an outer scope, you "shadowed it," silently covering it up until the scope ended. When they developed C#, they felt this was too counterintuitive, and too error prone. In C# it is a syntax error to shadow a variable from an outer scope. By introducing int i to the outer scope, it is now illegal for the for loops to introduce it themselves.
The variable declared in for loop has just scope inside for loop block, but when you declare a variable outside for loop, you cannot have same name variable inside the for loop, because it confuses compiler that which variable you mean in for loop body.
Like i will take your code as example:
int i =0;
for (int i = 0; i < 10; i++)
{
i = i+1; // now compiler is confused which i you mean here, so i complains on compile time that you have two with same name
}
So if you declare it between loops as you did, variable i has scope in both for loops so it is accessible in both for loops, so if you remove first loop it will still complain because of global scope of variable outside the loop:
for (int i = 0; i < 10; i++)
{
i = i+1; // now compiler is still confused which i you mean
}
int i =0;
I don't think it matters where you put int i;.
The compiler first scans the field, after which it starts scanning for expressions. It doesn't compile because the i is already recognized as a field.
There is nothing strange going on. In the second case you've defined an outer i and then try to redefine it in each loop.
Variables declared in a for statement are local to the loop, but you've already defined another variable with the same name in the outer scope.
I think you've already asked another scoping question assuming that the scope of a variable starts from the point of declaration ?
A variable's scope is the block in which it is defined, it isn't affected by its placement. While the compiler will refuse to use the variable before the declaration, it is still in scope
int i; You declare outside the loop is available for the current function. Either declare only outer int i, and remove int i from both loops, or just remove this outer variable.
See below code snippets
class scopes
{
static int j=20;
Console.WriteLine(j);
public static void Main()
{
int j=30;
Console.WriteLine(j);
return;
}
}
For above code , variable hiding is supported
see below code
public static int Main()
{
int j = 20;
for (int i=0; i < 10; i++)
{
int j = 30; //can't do this
Console.WriteLine(j + i);
}
return 0;
}
Here for above code variable hiding is not supported.
What is the reason behind this?
In the first case, there is at least a defined way to disambiguate between the two things, i.e. the this. prefix - inside the method, this.j is the field, where-as j is the member. As for why this is supported: speculation, but probably so that adding a field to the class (which could be in a different code file in the case of partial classes) doesn't cause random methods to start throwing compiler errors. Note that the meaning in of j in the method is identical before and after the field j is added.
In the second case, this is not a concern: adding locals can only impact the single local method, and there is no disambiguation syntax (i.e. which j do we mean), and no risk of accidental breakage from unrelated code.
I get the following error in Visual Studio 2008:
Error 1 A local variable named 'i' cannot be declared in this scope because it would give a different meaning to 'i', which is already used in a 'child' scope to denote something else
This is my code:
for (int i = 0; i < 3; i++)
{
string str = "";
}
int i = 0; // scope error
string str = ""; // no scope error
I understand that str ceases to exist once the loop terminates, but I also thought that the scope of i was confined to the for loop as well.
So i has the same scope as a variable declared just outside of the for loop?
Edit:
Just to be clear, I am using C#. I am debating removing the "C" tag. However, since the correct answer explains the difference between the two, I figure it makes sense to leave both tags.
I had an error in my code comment above:
for (int i = 0; i < 3; i++)
{
string str = "";
}
int i = 0; // scope error
string str = ""; // also scope error,
// because it's equivalent to declaring
// string str =""; before the for loop (see below)
I think you're all confusing C++ and C#.
In C++, it used to be that the scope of a variable declared in a for expression was external to the block that followed it. This was changed, some time ago, so that the scope of a variable declared in a for expression was internal to the block that followed it. C# follows this later approach. But neither has anything to do with this.
What's going on here is that C# doesn't allow one scope to hide a variable with the same name in an outer scope.
So, in C++, this used to be illegal. Now it's legal.
for (int i; ; )
{
}
for (int i; ; )
{
}
And the same thing is legal in C#. There are three scopes, the outer in which 'i' is not defined, and two child scopes each of which declares its own 'i'.
But what you are doing is this:
int i;
for (int i; ; )
{
}
Here, there are two scopes. An outer which declares an 'i', and an inner which also declares an 'i'. This is legal in C++ - the outer 'i' is hidden - but it's illegal in C#, regardless of whether the inner scope is a for loop, a while loop, or whatever.
Try this:
int i;
while (true)
{
int i;
}
It's the same problem. C# does not allow variables with the same name in nested scopes.
The incrementor does not exist after the for loop.
for (int i = 0; i < 10; i++) { }
int b = i; // this complains i doesn't exist
int i = 0; // this complains i would change a child scope version because the for's {} is a child scope of current scope
The reason you can't redeclare i after the for loop is because in the IL it would actually declare it before the for loop, because declarations occur at the top of the scope.
Yea. Syntactically: The new scope is inside the block defined by the curly strings. Functionally: There are cases in which you may want to check the final value of the loop variable (for example, if you break).
Just some background information: The sequence doesn't come into it. There's just the idea of scopes - the method scope and then the for loop's scope. As such 'once the loop terminates' isn't accurate.
You're posting therefore reads the same as this:
int i = 0; // scope error
string str = ""; // no scope error
for (int i = 0; i < 3; i++)
{
string str = "";
}
I find that thinking about it like this makes the answers 'fit' in my mental model better..
for (int i = 0; i < 10; i++)
{
Foo();
}
int i = 10; // error, 'i' already exists
----------------------------------------
for (int i = 0; i < 10; i++)
{
Foo();
}
i = 10; // error, 'i' doesn't exist
By my understanding of scope, the first example should be fine. The fact neither of them are allowed seems even more odd. Surely 'i' is either in scope or not.
Is there something non-obvious about scope I don't understand which means the compiler genuinely can't resolve this? Or is just a case of nanny-state compilerism?
By my understanding of scope, the first example should be fine.
Your understanding of scope is fine. This is not a scoping error. It is an inconsistent use of simple name error.
int i = 10; // error, 'i' already exists
That is not the error that is reported. The error that is reported is "a local variable named i cannot be declared in this scope because it would give a different meaning to i which is already used in a child scope to denote something else"
The error message is telling you what the error is; read the error message again. It nowhere says that there is a conflict between the declarations; it says that the error is because that changes the meaning of the simple name. The error is not the redeclaration; it is perfectly legal to have two things in two different scopes that have the same name, even if those scopes nest. What is not legal is to have one simple name mean two different things in nested local variable declarations spaces.
You would get the error "a local variable named i is already defined in this scope" if instead you did something like
int i = 10;
int i = 10;
Surely 'i' is either in scope or not.
Sure -- but so what? Whether a given i is in scope or not is irrelevant. For example:
class C
{
int i;
void M()
{
string i;
Perfectly legal. The outer i is in scope throughout M. There is no problem at all with declaring a local i that shadows the outer scope. What would be a problem is if you said
class C
{
int i;
void M()
{
int x = i;
foreach(char i in ...
Because now you've used i to mean two different things in two nested local variable declaration spaces -- a loop variable and a field. That's confusing and error-prone, so we make it illegal.
Is there something non-obvious about scope I don't understand which means the compiler genuinely can't resolve this?
I don't understand the question. Obviously the compiler is able to completely analyze the program; if the compiler could not resolve the meaning of each usage of i then how could it report the error message? The compiler is completely able to determine that you've used 'i' to mean two different things in the same local variable declaration space, and reports the error accordingly.
It is because the declaration space defines i at the method level. The variable i is out of scope at the end of the loop, but you still can't redeclare i, because i was already defined in that method.
Scope vs Declaration Space:
http://csharpfeeds.com/post/11730/Whats_The_Difference_Part_Two_Scope_vs_Declaration_Space_vs_Lifetime.aspx
You'll want to take a look at Eric Lippert's answer (who by default is always right concerning questions like these).
http://blogs.msdn.com/ericlippert/archive/2009/08/03/what-s-the-difference-part-two-scope-vs-declaration-space-vs-lifetime.aspx
Here is a comment from eric on the above mentioned post that I think talks about why they did what they did:
Look at it this way. It should always
be legal to move the declaration of a
variable UP in the source code so long
as you keep it in the same block,
right? If we did it the way you
suggest, then that would sometimes be
legal and sometimes be illegal! But
the thing we really want to avoid is
what happens in C++ -- in C++,
sometimes moving a variable
declaration up actually changes the
bindings of other simple names!
From the C# spec on local variable declarations:
The scope of a local variable declared
in a local-variable-declaration is the
block in which the declaration occurs.
Now, of course, you can't use i before it is declared, but the i declaration's scope is the entire block that contains it:
{
// scope starts here
for (int i = 0; i < 10; i++)
{
Foo();
}
int i = 10;
}
The for i variable is in a child scope, hence the collision of variable names.
If we rearrange the position of the declaration, the collision becomes clearer:
{
int i = 10;
// collision with i
for (int i = 0; i < 10; i++)
{
Foo();
}
}
Yea, I second the "nanny-state compilerism" comment. What's interesting is that this is ok.
for (int i = 0; i < 10; i++)
{
}
for (int i = 0; i < 10; i++)
{
}
and this is ok
for (int i = 0; i < 10; i++)
{
}
for (int j = 0; j < 10; j++)
{
var i = 12;
}
but this is not
for (int i = 0; i < 10; i++)
{
var x = 2;
}
var x = 5;
even though you can do this
for (int i = 0; i < 10; i++)
{
var k = 12;
}
for (int i = 0; i < 10; i++)
{
var k = 13;
}
It's all a little inconsistent.
EDIT
Based on the comment exchange with Eric below, I thought it might be helpful to show how I try to handle loops. I try to compose loops into their own method whenever possible. I do this because it promotes readability.
BEFORE
/*
* doing two different things with the same name is unclear
*/
for (var index = 0; index < people.Count; index++)
{
people[index].Email = null;
}
var index = GetIndexForSomethingElse();
AFTER
/*
* Now there is only one meaning for index in this scope
*/
ClearEmailAddressesFor(people); // the method name works like a comment now
var index = GetIndexForSomethingElse();
/*
* Now index has a single meaning in the scope of this method.
*/
private void ClearEmailAddressesFor(IList<Person> people)
{
for (var index = 0; index < people.Count; index++)
{
people[index].Email = null;
}
}
In the first example, the declaration of i outside of the loop makes i a local variable of the function. As a result, it is an error to have another variable name i declared within any block of that function.
The second, i is in scope only during the loop. Outside of the loop, i can no longer be accessed.
So you have seen the errors, but there is nothing wrong with doing this
for (int i = 0; i < 10; i++)
{
// do something
}
foreach (Foo foo in foos)
{
int i = 42;
// do something
}
Because the scope of i is limited within each block.
Or is just a case of nanny-state
compilerism?
Exactly that. There is no sense in "reusing" variable names in the same method. It's just a source of errors and nothing more.
Me thinks that the compiler means to say that i has been declared at the method level & scoped to within the for loop.
So, in case 1 - you get an error that the variable already exists, which it does
& in case 2 - since the variable is scoped only within the for loop, it cannot be accessed outside that loop
To avoid this, you could:
var i = 0;
for(i = 0, i < 10, i++){
}
i = 10;
but I can't think of a case where you would want to do this.
HTH
you need to do
int i ;
for ( i = 0; i < 10; i++)
{
}
i = 10;
class Test
{
int i;
static int si=9;
public Test()
{
i = 199;
}
static void main()
{
for (int i = 0; i < 10; i++)
{
var x = 2;
}
{ var x = 3; }
{ // remove outer "{ }" will generate compile error
int si = 3; int i = 0;
Console.WriteLine(si);
Console.WriteLine(Test.si);
Console.WriteLine(i);
Console.WriteLine((new Test()).i);
}
}
}