Strange behaviour of switch case with boolean value - c#

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?

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.

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.

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

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

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();

Related

My BizTalk functoid returns true value regardless of the boolean being passed

I am having an issue on my BizTalk application
I have customized the functoid to change value based on the boolean it has received her is the code
public string GetBoolMark(bool param1)
{
string returnValue = "0";
if (param1 == true )
{
returnValue = "1";
}
return returnValue;
}
I am having an issue that the value always returns the true value. I am using BizTalk server 2013 R2
Change the type of param1 from bool to string.
Parse it carefully inside you function to a boolean, and use that boolean to decide what to return.
public string GetBoolMark(string param1)
{
bool condition;
string returnValue = "0";
if (bool.TryParse(param1, out condition) && condition)
{
returnValue = "1";
}
return returnValue;
}
When using the inline C# in a scripting functoid, I always find it easier to assume all parameters are strings.
If you use other type, some implicit parsing will be performed for you. I'd rather perform the parsing myself explicitly because I don't know exactly how the implicit parsing works.
If it is indeed xs:boolean, you can do:
public MyFunctoid(string MyParam)
{
if(MyParam == "true")
{
return "It was true!";
}
return "It was false!";
}
This is because the value of MyParam can be one of only 3 things, 'true', 'false' or ''.  You only need to test for 'true'.  This is one case where a [Try]Parse is not necessary.

C# Optional Out Parameter

Is there any way to make an out parameter of a method optional? I have a method that needs several parameters to return null most of the time, but sometimes they will have a value. I am trying to find out if there is a better way to accomplish this than by setting the values to null first, or setting them to null after the if/else. This may be the only way to do it, but it would be nice if there were optional out parameters or something equivalent. Here is the code:
private static void GetInitInfo(string initLine, string ncPointType, out double? relinquishDefault, out bool? ignoreRelinquishDefault, out bool? closedForStart, out bool? adjustDisabled)
{
relinquishDefault = null;
ignoreRelinquishDefault = null;
closedForStart = null;
adjustDisabled = null;
switch (ncPointType)
{
case "MSD":
adjustDisabled = LastToken<bool?>(initLine);
break;
case "BO":
relinquishDefault = SecondToken<double>(initLine);
closedForStart = ThirdToken<bool?>(initLine);
ignoreRelinquishDefault = !ForthToken<bool?>(initLine);//ignoreRelDef would be reverse of use initial value
break;
case "MSO":
closedForStart = SecondToken<bool?>(initLine);
relinquishDefault = ThirdToken<double>(initLine);
ignoreRelinquishDefault = !ForthToken<bool?>(initLine);//ignoreRelDef would be reverse of use initial value
break;
case "AD":
relinquishDefault = ThirdToken<double>(initLine);
ignoreRelinquishDefault = false;
break;
case "BD":
relinquishDefault = SecondToken<double>(initLine);
adjustDisabled = LastToken<bool?>(initLine);
ignoreRelinquishDefault = false;
break;
case "AOS":
relinquishDefault = FirstToken<double>(initLine);
ignoreRelinquishDefault = !ThirdToken<bool?>(initLine);//ignoreRelDef would be reverse of use initial value
break;
}
}
This isn't not allowed according to the C# 4.0 Spec: section 21.1.
A workaround is to overload with another method that does not have out or ref parameters.
I believe this question is asking about having to assign values inside the method with out parameters, and whether there is any way to circumvent that, i.e. by leaving the values unassigned rather than explicitly having to assign them null.
e.g. Do you have to write:
public bool OutMethod(out int? output)
{
output = null;
return true;
}
Or is there a way to do something like:
public bool OutMethod(out int? output)
{
return true;
}
With the same result?
Short answer is no, this can't be avoided. See the documentation for an example which includes assigning null explicitly, and states:
Note that the third argument is assigned to null. This allows methods to return values optionally.
Examples of this can also be found in the .NET framework. e.g. Dictionary<TKey,TValue>'s TryGetValue method:
public bool TryGetValue(TKey key, out TValue value)
{
int num = this.FindEntry(key);
if (num >= 0)
{
value = this.entries[num].value;
return true;
}
value = default(TValue);
return false;
}
Note the explicit assignment to default(TValue)
Use the overload with signature that does not have out parameters:
private static void GetInitInfo(string initLine, string ncPointType)
{
double? relinquishDefault;
bool? ignoreRelinquishDefault;
bool? closedForStart;
bool? adjustDisabled;
GetInitInfo( initLine, ncPointType, out relinquishDefault, out ignoreRelinquishDefault,
out closedForStart, out adjustDisabled);
}
The explanation is quite simple: You can do it. Just assign an out parameter inside the method to the desired value.
Now you can ask yourself, why can't we do that in the method signature? Well, let us have a look at the normal optional value parameters. They are assigned a predefined value if they are not assigned by the caller. So caller knows the value, which will be passed if the parameter is not set explicitly. It has a control of it and it is responsible for that decision.
Since the caller of the method is NOT responsible for the assignment of the out parameter, it makes no sense to offer a default value. The only thing you could achieve, by having a default out parameter value is to let the caller know what one of the possible values of that out parameter would be. But would that make sense? When will this value be used? Under what condition? All this is still hidden from the caller. So there is no real benefit from having an optional out parameter value, apart from having a possiblity to set it inside the signature instead of the method body.
So, having that said, the following would not make much sense:
public bool TrySomething(out string outObject = "default value") { ... }
However, what would be cool is to allow the following method
public bool TrySomething(out string outObject) { ... }
to be invoked as follows:
bool result = TrySomething();
And have that behind the scenes equivalent to:
string dummyWhichWillNeverBeUsed;
bool succeeded = TrySomething(out dummyWhichWillNeverBeUsed);
Unfortunately, that is not allowed.
And of course, as explained in other answers, you can always have overloads without out parameter.

string to bool inline conversion

What I currently have:
bool okPress = !string.IsNullOrEmpty(Ctx.Request["okPress"]) &&
Convert.ToBoolean(Ctx.Request["okPress"]);
Correct me if I'm wrong here, but wouldn't this throw a FormatException if the string isn't "true/True" or "false/False"? Is there any way to handle the conversion in one row, without having to worry about exceptions? Or do I need to use Boolean.TryParse?
You can use Boolean.TryParse:
bool okPress;
bool success = Boolean.TryParse(Ctx.Request["okPress"]), out okPress);
For what it's worth, here a "one-liner", create following extension which might be useful especially in LINQ queries:
public static bool TryGetBool(this string item)
{
bool b;
Boolean.TryParse(item, out b);
return b;
}
and write:
bool okPress = Ctx.Request["okPress"].TryGetBool();
IF you didn't want to use TryParse You could do something like
bool okPress = !string.IsNullOrEmpty(Ctx.Request["okPress"]) &&
(Ctx.Request["okPress"].ToLower()=="true");
This way if the string is not true/false it will just assume false for you with no exceptions thrown.
This does of course assume that you are happy for a value of "fish" to be treated as false rather than as an exception.
Better though is to just not do it as a single line. You don't generally have a maximum number of lines of code so two or three simple lines of code are often better than one complicated line of code...
Why don't you compare the string against true?
bool okPress = !string.IsNullOrEmpty(Ctx.Request["okPress"]) &&
String.Compare(Ctx.Request["okPress"], "true", StringComparison.OrdinalIgnoreCase) == 0
You can use TryParse method of Boolean class as you said.
Tries to convert the specified string representation of a logical
value to its Boolean equivalent. A return value indicates whether the
conversion succeeded or failed.
bool result = Boolean.TryParse(Ctx.Request["okPress"]), out okPress);
It returns true if value was converted successfully; otherwise, false.
Your inline conversion.
public static bool TryParseAsBoolean(this string expression)
{
bool booleanValue;
bool.TryParse(expression, out booleanValue);
return booleanValue;
}
bool okPress = Ctx.Request["okPress"].TryParseAsBoolean();

Bool Variable and string value compare in C#

If I declared a bool isTrue = false; // init it to false
and I can get the value from a string strVal = T; // I assumed it is the TRUE value
I heard it is not a good code style to compare string in C# like
if (isTrue.tostring() == strVal) {}.
Some time, I covert the the string variable to enum then I can compare it more convenient.
Is there any good method to do it?
Yes, you parse the string into a boolean first.
Try this:
bool someBool = false;
string boolVal = "true";
bool stringBool;
bool.TryParse(boolVal, out stringBool);
if (someBool == boolVal)
{
}
Alternatively to handle 'T' and 'F' try these methods:
public bool ParseString(string maybeBool)
{
return ParseString(maybeBool, false);
}
public bool ParseString(string maybeBool, bool def)
{
bool stringBool;
if (bool.TryParse(maybeBool, out stringBool))
return stringBool;
if (string.Equals(maybeBool, "T", StringComparison.OrdinalIgnoreCase))
return true;
if (string.Equals(maybeBool, "F", StringComparison.OrdinalIgnoreCase))
return false;
return def;
}
Try bool.Parse() method instead.
bool.Parse(boolVal) == isTrue
There is no need to convert boolean values to strings in order to compare the two. You can simply compare the two boolean values directly:
if (isTrue == boolVal) {}
Update: (following updated question)
You can parse a string into a boolean and use the resulting boolean in your comparison (as above), using either bool.Parse or bool.TryParse.
you may compare boolean type instead.
bool temp = bool.Parse(strVal);
if(isTrue == temp)
Yet another version which i use a lot is simply Convert.ToBoolean(stringFromBoolVal)
regards
If you really want to do string comparisons:
if (string.Equals(isTrue.ToString(), strValue)) { }
How about trying this simple way to determine the value of bool variable isTrue:
isTrue = strVal == "T";
isTrue will return true if the strVal is equaled to "T". And return false if not.

How can I use the string value of a C# enum value in a case statement?

I have defined a C# enum as
public enum ORDER
{
...
unknown,
partial01,
partial12,
partial23,
}
and can use its value as a string as in:
string ss = ORDER.partial01.ToString();
However when I try to use it in a case statement it fails to compile:
string value = ...
switch (value)
{
case null:
break;
case "s":
// OK
break;
case ORDER.partial01.ToString():
// compiler throws "a constant value is expected"
break;
...
I thought enums were constants. How do I get around this?
(I cannot parse the value into an enum as some of the values are outside the range)
Since C# 6, you can use: case nameof(SomeEnum.SomeValue):
Nameof is evaluated at compile time, simply to a string that matches the (unqualified) name of the given variable, type, or member. Naturally, it changes right along should you ever rename the enum option name.
Convert the string in your switch to an enum value.
(ORDER)Enum.Parse(typeof(ORDER), value, true);
The enum is a constant, but the result of .ToString() is not. As far as the compiler is concerned, it is a dynamic value. You probably need to convert your switch case into a series of if/else statements
As an alternative to using if .. else, you could convert your string to an enum first. It would probably not make much sense if the number of options is small though:
if (Enum.IsDefined(typeof(ORDER), value))
{
switch ((ORDER)Enum.Parse(typeof(ORDER), value)
{
case ORDER.partial01:
// ...
break;
case ORDER.partial12:
// etc
}
}
else
{
// Handle values not in enum here if needed
}
*sigh* if only there was a built-in T Enum.Parse<T>(string value), and a TryParse version :)
You designed this as an enum for a reason, but you're not really making use of it as an enum. Why are you taking the enum value and converting it to a string to then use in the switch instead of simply using the enum?
You said that you can't parse this in to an enum because some of the values are outside the enum range. The question to ask then is, "Why?" What is the point of having the enum if you are allowing values that aren't defined? What is it that you want to happen when you get a value that isn't defined? If it's the same thing for any undefined value, then you can use the default case. If it's not, then you can include additional cases that match the numeric representation.
If you really do get strings back, then you probably don't want to use an enum. Instead you want to create a public static class containing public string constants, which you can then use in your switch. The trick here is that the evaluation will be done in a case sensitive manner.
public static class Order
{
public const string Unknown = "Unknown";
public const string Partial01 = "Partial01";
public const string Partial12 = "Partial12";
public const string Partial23 = "Partial23";
}
string value = Order.Partial01
switch (value)
{
case Order.Partial01:
break;
default:
// Code you might want to run in case you are
// given a value that doesn't match.
break;
}
(You might also want to clean up your casing.)
As Thorarin indicated, if your switch statement can contain only enum cases, convert your string to an enum first. At least as of .Net framework 4, you can use the Enum.TryParse()<TEnum> method as defined here and do something like:
ORDER orderEnum = ORDER.unknown;
Enum.TryParse<ORDER>(value, out orderEnum);
switch (orderEnum)
{
case ORDER.unknown:
// perhaps do something to deal with cases not matching
// to known enum values, based on the string value
break;
case ORDER.partial01:
case ORDER.partial12:
case ORDER.partial23:
// map value to known cases, etc.
break;
}
Enum values are constants, but you're trying to use the results of a method (ORDER.partial01.ToString()), not a constant.
The best option, in my opinion, would be to just switch this around to using if/else if/else statements, instead of a switch. This would allow you to use the logic you are desiring.
Alternatively, if you switch your string into the enum value, you can switch on the enum values directly. You cannot switch on the enum + null + other strings, though, in one switch.
Couldn't you just instead say
case "partial01":
?
enums are constant but ToString() is a function returning a value. based on the instance of the enum object it's being called on.
That is the two statements:
ORDER.partial01.ToString()
ORDER.partial02.ToString()
calls the same function but returns two different values, so the call to the function .ToString() is in it self not a constant value.
This is not a static value as far as the compiler is concerned, since it is a function call:
ORDER.partial01.ToString()
Therefore, you can't use it as a comparison in a case statement. However, you can simply do this:
case "partial01"
That would work, since the enum value and the string are identical.
Use Extension
public static string ToGender(this Gender enumValue)
{
switch (enumValue)
{
case Gender.Female:
return "Female";
case Gender.Male:
return "Male";
default:
return null;
}
}
Example
Gender.Male.ToGender();
simply you can define a global variable
static ORDER orderstr;
now you can set the value of orderstr anywhere in the page
public enum ORDER
{
unknown,
partial01,
partial12,
partial23,
}
switch (orderstr)
{
case Order.Partial01:
break;
default:
break;
}

Categories

Resources