views:

497

answers:

8
+3  Q: 

c# switch problem

I'm new to programming and having a problem with the following code:

    private string alphaCoords(Int32 x)
    {
        char alphaChar;

        switch (x)
        {
            case 0: alphaChar = 'A'; break;
            case 1: alphaChar = 'B'; break;
            case 2: alphaChar = 'C'; break;
            case 3: alphaChar = 'D'; break;
            case 4: alphaChar = 'E'; break;
            case 5: alphaChar = 'F'; break;
            case 6: alphaChar = 'G'; break;
            case 7: alphaChar = 'H'; break;
            case 8: alphaChar = 'I'; break;
            case 9: alphaChar = 'J'; break;
        }

        return alphaChar.ToString();
    }

The compiler says: Use of unassigned local variable 'alphaChar'

But I'm assigning it in my switch block.

I'm sure this is my fault as I dont know enough about programming.

Please advise.

Thanks.

+29  A: 

You're assigning it if x is 0-9. What would you expect it to do if x were 123 though? While you may know that only values between 0 and 9 will be passed in, the compiler doesn't - so it needs to consider what would happen otherwise.

One way to avoid this is to have a default case in your switch statement, which you can use to throw an exception if the value isn't in the expected range:

switch (x)
{
    case 0: alphaChar = 'A'; break;
    case 1: alphaChar = 'B'; break;
    case 2: alphaChar = 'C'; break;
    case 3: alphaChar = 'D'; break;
    case 4: alphaChar = 'E'; break;
    case 5: alphaChar = 'F'; break;
    case 6: alphaChar = 'G'; break;
    case 7: alphaChar = 'H'; break;
    case 8: alphaChar = 'I'; break;
    case 9: alphaChar = 'J'; break;
    default: throw new ArgumentOutOfRangeException();
}

Here's a slightly simpler alternative though, which removes your switch statement completely:

if (x < 0 || x > 9)
{
    throw new ArgumentOutOfRangeException();
}
char alphaChar = (char)('A' + x);

Note that you do need to exercise care when using arithmetic like this. In Java and C# the underlying representation is guaranteed to be Unicode, which makes life a lot easier. I believe it's fine for things like this (and hex parsing/formatting) but when you venture into more exotic scenarios it would fail. Then again, that's true for a lot of code simplification techniques... if they're applied inappropriately, you end up with a mess.

Jon Skeet
i only want to handle values from 0 to 9. no values other than these will ever be passed.
iEisenhower
@ikurtz: Then throwing an exception if there *is* a value other than 0 to 9 is the right thing to do.
Jon Skeet
But the compiler doesn't know that and it cannot verify or ensure that.
Benjamin Podszun
your code is clean. thanks for the help.
iEisenhower
Downvoted for (char)('A' + x). In a Unicode world, using arithmetic to manipulate character values is a very bad practice.
Cylon Cat
@Cylon Cat: In an unrestricted range, I'd agree - but here we've already established the range of values for `x`, and the results are clearly defined. In what way is this "very bad practice"? What do you think will go wrong with this code? Can you point to any situation in which the results would be undefined or incorrect? There's a big difference between *careless* arithmetic with character data being a bad idea, and *all* such arithmetic being a bad idea.
Jon Skeet
@Jon, "In the restricted range," yes, it works. My concern is about establishing bad habits, and reliance on characteristics of the underlying representation. Two immediate cases come to mind, though. First, this is an English-only technique; languages with accents, umlauts, etc. need to avoid this. Second, I grew up in EBCDIC, where even the basic English alphabet was not in a single contiguous range ('A'-'J' = xC0 to xC9; 'K'-'T' = xD0 to xD9; 'U-Z' = xE0 to xE5). So generally, I trust pointer arithmetic more than I trust character arithmetic, and I don't trust pointer arithmetic.
Cylon Cat
@Cylon Cat: But as you said, we live "in a Unicode world" - so you can absolutely rely on what the arithmetic will do (within C# and Java). You can rely on the underlying representation because it's explicitly specified. The business about accents is irrelevant to **this code** because only A-J needs to be considered. I'll add a note to the answer to give a warning about trying to apply this *too* widely, but for this specific case I have no qualms about it.
Jon Skeet
There is a damn good reason you have 129K rep.
ChaosPandion
Reputation can give you a clue about how sharp the answer is but it cannot support the answer by itself. Anyway I'm with Jon (and I'm an spanish speaker/programmer). 1) In THIS case English is not the language... "A" to "J" is the language. So it's ok. 2) It's more teaching to KNOW deeply what's happening and what can be wrong than ignoring things. If Jon says: "be very careful, it's ok here but a bad idea elsewhere...", then he's teaching. oh, ah +1 by the way :)
helios
+1  A: 

You need to add a default to your switch statement.

The compiler is stating that there are some cases which will not assign a value to the variable. So adding

default:
  alphaChar = 'x'
break;

will tell the compiler "so in case I miss some scenario, make the value this"

or in the case of not wanting to assign a default:

  default: throw new Exception();

This is not necessarily better but another way of doing it:

 private string alphaCoords(Int32 x)
    {
      if(x >= 0 && x =< 9)
           return ((char)(x + 65)).ToString();
      else
        throw new ArgumentException();
    }
Kevin
i dont want to add a default as the values can only be from 0 to 9.
iEisenhower
A: 

The compiler has no way of knowing that the variable x can only contain numbers up to 9 (which is what you check in your switch). Since the default case is missing from your switch it can happen that alphaChar remains unassigned. You can either add a default case or assign the variable a value before the switch.

Joey
A: 

Add a default to your switch, because if x is 10, alphaChar will never be assigned.

Yuriy Faktorovich
+2  A: 

The compiler is complaining because alphaChar is possibly undefined -- if it is not one of the values in your switch then it will not have been defined. You can do one of the following things:

  • Set an initial value of char which will be carried through if none of the switch conditions is true.
  • Add a "default" clause to your switch statement.
kdt
A: 

After you declare the variable char alphaChar, you should "assign" a value to it (set it to be equal to something), even though you expect it to get a value in the switch statement.

You could assign it 'A' or '0' or pretty much anything.

You can do that in the declaration like this

char alphaChar = 'A';

Or you can do it separately

char alphaChar;    
alphaChar = 'A';
DOK
+2  A: 

Before its first use local variable must be definitely assigned (according to C# specification rules). In this particular case switch construct doesn't guarantee that alphaChar will be definitely assigned thus compiler error. You can provide initial value to alphaChar and thus it will be definitely assigned.

Dzmitry Huba
A: 

You are assigning value to the variable 'alphaChar' based on some condition. Imagine a scenario where the variable 'x' contains value other than 0 to 9. Suppose it contains 10. Then none of the case conditions will be satisfied by 'x', so 'alphaChar' will not be assigned any value, as a result it will be totally uninitialized. So when you are converting 'alphaChar' to string, it is converting some garbage value to string and returning it to the calling method. This is the reason why you are getting that message.

If you want to get a simple solution, then add the following code below "case 9: alphaChar = 'J'; break;" -

default: return null;

and check in the calling methods whether this 'alphaCoords' function returns null or not, like this -

if(alphaCooord(10) == null) { // x contains value other than 0 to 9 } else { // x contains value between 0 to 9, so the returned value will be the string // representation of the corresponding character }

In this way your code won't be too complex, or you won't need to throw or handle any exceptions or something like that.

Hope that helps :)

Night Shade