3

My question is not about how to solve this error(I already solved it) but why is this error with boolean value.

My function is

private string NumberToString(int number, bool flag)
{
    string str;

    switch(flag)
    {
        case true: 
            str = number.ToString("00");
            break;
        case false:
            str = number.ToString("0000"); 
            break;
    }

    return str;
}

Error is Use of unassigned local variable 'str'. Bool can only take true or false. So it will populate str in either case. Then why this error?

Moreover this error is gone if along with true and false case I add a default case, but still what can a bool hold apart from true and false?

Why this strange behaviour with bool variable?

Nikhil Agrawal
  • 47,018
  • 22
  • 121
  • 208
  • 1
    I don't think the compiler takes the type's possible values into account when checking for definite assignment inside a `switch` statement. In other words, you would get the same error if `flag` was an `int` and you had 4,294,967,296 `case` statements ranging from `-2,147,483,648` to `2,147,483,647`. – Frédéric Hamidi Jun 19 '12 at 09:17
  • It could be `null` I guess `bool? flag = null;` – Bali C Jun 19 '12 at 09:17
  • The same question has been asked before, looking for duplicate now. – leppie Jun 19 '12 at 09:18
  • Is this a runtime error or a compile error or warning? Try string str = ""; – Oliver Kötter Jun 19 '12 at 09:19
  • I guess the compiler simply is not smart enough to recognize that you have cases for all possible values in your select statement. Initialize str by using 'string str = "";' should help. – Oliver Kötter Jun 19 '12 at 09:21
  • And Bali is right, bool cannot just be true or false but also null. – Oliver Kötter Jun 19 '12 at 09:22
  • @BaliC: I have bool and not bool?. Bool is value type so cannot take null. – Nikhil Agrawal Jun 19 '12 at 09:23
  • @Ollie: My question is not about how to solve this error(I already solved it) but why is this error with boolean value. and Moreover who said bool can be null. bool? can be null but not bool. Its a value type and not reference type. – Nikhil Agrawal Jun 19 '12 at 09:24

5 Answers5

9

Writing a switch statement on a boolean variable seems kinda wasty to me. Why not use the conditional operator (?:):

private string NumberToString(int number, bool flag)
{
    return flag ? number.ToString("00") : number.ToString("0000"); 
}

The code seems a bit more concise and you don't need local variables.

But back to your question about why your code doesn't compile => it is because variables must always be assigned and this assignment should not happen inside conditional statements.

Darin Dimitrov
  • 1,023,142
  • 271
  • 3,287
  • 2,928
  • You said assignment should not happen inside conditional statements. Right? Wrong. Add a default case conditional statement and it will not give error. – Nikhil Agrawal Jun 19 '12 at 09:28
  • Yes, adding a default case statement would indeed fix the error. But as I said, writing a switch statement with true, false and default cases seems absolutely insane and a good candidate for thedailywtf.com :-) – Darin Dimitrov Jun 19 '12 at 09:29
  • @NikhilAgrawal: It's to keep it as simple as possible for the compiler and also to prevent the programmer from simple bugs. So if you show that you've thought a little bit about it(default case), the compiler allows it. – Tim Schmelter Jun 19 '12 at 09:31
  • What if there was more lines of code inside switch case? What you have provided is an alternative and not an explanation to cause. – Nikhil Agrawal Jun 19 '12 at 09:31
  • I guess that's because of your oversimplified example. If there are other lines, simply use `if/else` with boolean variables, not switches. With if/else you don't need to worry about assigning as well and you have one less thing to worry about => the default case which doesn't make any sense with boolean variables. – Darin Dimitrov Jun 19 '12 at 09:32
  • @NikhilAgrawal: You can find the explanation at the end of [Eric Lipperts answer](http://stackoverflow.com/a/8933935/284240). _"The reason this is illegal in C# is because using an unassigned local has high likelihood of being a bug. We simply make it illegal, and then the compiler prevents you from ever having such a bug."_ – Tim Schmelter Jun 19 '12 at 09:34
  • 2
    Or even better: `return number.ToString(flag ? "00" : "0000")` :) – nawfal Aug 07 '13 at 22:01
7

The error you get is about string variable and not boolean possible values.

The fact that there is no way that noone of cases run, is a true (in this case), but compiler doesn't go so far in analyzing the code. It just looks on variable that is not assigned and used in some conditions and there is not default one, so suppose that there could be some case when it remains unassigned.

Tigran
  • 61,654
  • 8
  • 86
  • 123
4

I think, you are trying to ask, why str variable is unassigned, as the switch statement's cases will assign it some value, but the compiler can't determine whether it will fall in any of the case statement, That is why you are getting this error on returning str.

If you add a default case with string assignment, then the compiler will know for sure that, the str will hold some value and that is why you don't get error

Habib
  • 219,104
  • 29
  • 407
  • 436
3
private string NumberToString(int number, bool flag)
{
    string str = "";

    switch(flag)
    {
        case true: 
            str = number.ToString("00");
            break;
        case false:
            str = number.ToString("0000"); 
            break;
    }

    return str;
}

write this string str = ""; - you should assign value

if you add default case there is no chance to fall through the switch cases without assigning. Now it is

levi
  • 3,451
  • 6
  • 50
  • 86
0

Well, there's been good explanation for causes of this issue, but there is one more solution to the problem, which was not mentioned. Just put default instead of second case:

    private string NumberToString(int number, bool flag)
    {
        string str;

        switch (flag)
        {
            case true:
                str = number.ToString("00");
                break;
            default:
                str = number.ToString("0000");
                break;
        }

        return str;
    }

It leaves compiler with no further thoughts about flag variable value as we always assign a default value in our switch statement.

Also consider if-else statement equivalent solution:

    private string NumberToString(int number, bool flag)
    {
        string str;

        if (flag)
            str = number.ToString("00");
        else
            str = number.ToString("0000");

        return str;
    }

I am not particularly fond of 'one-liners' (one line solutions), as they lack extendability and moreover - readability, but as the last resort just use ternary operators like this:

    private string NumberToString(int number, bool flag)
    {
        return flag ? number.ToString("00") : number.ToString("0000");
    }

While I am at it - consider using extension method + defaulting boolean to false, for example:

public static class intExtensions
{
    public static string NumberToString(this int number, bool flag = false)
    {
        return flag ? number.ToString("00") : number.ToString("0000");
    }
}

and then in main class:

        int intVal = 56;
        string strVal1 = intVal.NumberToString(true);
        string strVal2 = intVal.NumberToString();
Alex
  • 4,607
  • 9
  • 61
  • 99