0

I have a couple of variables that need to be assigned inside a for loop. Apparently, when the loop exits, C# ignores whatever happened in there, and the variables are returned to their original status. Specifically, I need them to be the last and next-to-last elements of a List. Here's the code:

int temp1, temp2;
for (int i = 0; i < toReturn.Count; i++) {
     if (i == toReturn.Count - 2) { // Next-to-last element
         temp1 = toReturn[i];
     } else if (i == toReturn.Count - 1) { // Last element
         temp2 = toReturn[i];
     }
}
// At this point, temp1 and temp2 are treated as uninitialized

Note: Nevermind the bad variable names, they're really temporary variables. Anything more complex would confuse things.

Now, there are two ways (that I know of) to solve this: one is figuring out how to make the variables live after the loop exits, the other is to do something like in Python, where you can do temp = my_list[-1] to get the last element of a list. Is any of these possible in C#?

Edit: When I try to compile, I get a "use of unassigned local variable 'temp1'" error. This code isn't even run, it's just sitting inside of a method that never gets called. If this helps, I'm trying to use the variables inside another loop.

Javier
  • 4,552
  • 7
  • 36
  • 46
  • 1
    Are you saying the compiler is warning that temp1 and temp2 are not initialized? Or that they should be set but never are (the observable value is uninitialized)? – Michael Sep 29 '09 at 20:54
  • 1
    In C# the variables are not returned to their original status after a loop. They will retain the value set within the loop as long as the variable was not created within the loop. – Josh Mein Sep 29 '09 at 20:55

6 Answers6

11

Why not just do...

int temp1 = 0;
int temp2 = 0;
    if (toReturn.Count > 1)
        temp1 = toReturn[toReturn.Count - 2];
    if (toReturn.Count > 0)
        temp2 = toReturn[toReturn.Count - 1];
Chris Arnold
  • 5,753
  • 5
  • 35
  • 55
5

If toReturn.Count is 0, the loop never runs and temp1 and temp2 are never initialized.

Michael
  • 54,279
  • 5
  • 125
  • 144
  • That's guaranteed not to happen. – Javier Sep 29 '09 at 20:55
  • Are you seeing a compiler error or warning? Or are you saying that the observed values indicate it hasn't been set? For a compiler warning, the compiler can't tell that toReturn.Count is always greater than 0. – Michael Sep 29 '09 at 20:56
  • 4
    It doesn't matter as far as compiler is concerned, since it cannot reasonably prove that it never happens, which is why it complains about variables being _potentially_ uninitialized. Just initialize them (e.g. assign 0) when you declare them, and it will compile and work. – Pavel Minaev Sep 29 '09 at 20:56
  • Well, that makes sense. I still like the other method better. – Javier Sep 29 '09 at 21:05
  • "That's guaranteed not to happen." The compiler doesn't believe you. And you haven't been around long enough if you've never seen an error message with the text, "This can never happen." – Brian Sep 29 '09 at 21:24
1

What's this do?

if (toReturn.Count > 1) {
    temp1 = toReturn[toReturn.Count - 2]
    temp2 = toReturn[toReturn.Count - 1]
}
Gordon Bell
  • 13,337
  • 3
  • 45
  • 64
0

try to give temp1 and temp2 an initial value i.e 0 or whatever is appropriate because they might never be initialized

Hannoun Yassir
  • 20,583
  • 23
  • 77
  • 112
  • To expand: *you* know temp1 and temp2 will be set. Your code more-or-less guarantees that. But because the assignments happen inside if-statements, the *compiler* has no understanding that temp1/temp2 will be set. As far as it is concerned, it is possible that the If statements will never be true, and the assignment will never happen. – abelenky Sep 29 '09 at 21:06
0
int temp1 = 0; // Or some other value. Perhaps -1 is appropriate.
int temp2 = 0; 

for (int i = 0; i < toReturn.Count; i++) {
     if (i == toReturn.Count - 2) { // Next-to-last element
         temp1 = toReturn[i];
     } else if (i == toReturn.Count - 1) { // Last element
         temp2 = toReturn[i];
     }
}

The compiler requires that temp1 and temp2 are definitely assigned before trying to read their values. The compiler doesn't know your for-loop will assign the variables. It doesn't know if the for loop ever runs at all. It also doesn't know if your if-conditions will ever be true.

The above code makes sure that temp1 and temp2 have been assigned to something. If you want to be sure whether temp1 and temp2 have been assigned in the loop, consider keeping track of this:

int temp1 = 0;
int temp2 = 0;
bool temp1Assigned = false;
bool temp2Assigned = false;

for (int i = 0; i < toReturn.Count; i++) {
     if (i == toReturn.Count - 2) { // Next-to-last element
         temp1 = toReturn[i];
         temp1Assigned = true;
     } else if (i == toReturn.Count - 1) { // Last element
         temp2 = toReturn[i];
         temp2Assigned = true;
     }
}
Joren
  • 14,472
  • 3
  • 50
  • 54
0

If you want a default value:

int count = toReturn.Count;
int temp1 = count > 1 ? toReturn[count - 2] : 0;
int temp2 = count  > 0 ? toReturn[count - 1] : 0;

If you don't care about default value and have previous checks for count in place:

int count = toReturn.Count;
int temp1 = toReturn[count - 2];
int temp2 = toReturn[count - 1];
eglasius
  • 35,831
  • 5
  • 65
  • 110