replace strings with enums in switch statment - c#

I'm using Visual Studio 2008 and trying to convert this switch statement
switch (salesOrderPayment.PaymentCardKey.ToUpper()) {
case "MC":
ValidateCreditCard(salesOrderPayment,errorMessages);
break;
case "VISA":
ValidateCreditCard(salesOrderPayment, errorMessages);
break;
case "TELECHECK":
//ValidateTelecheck(salesOrderPayment, errorMessages);
ValidateAchCheck(salesOrderPayment, errorMessages);
break;
case "ACH":
ValidateAchCheck(salesOrderPayment, errorMessages);
break;
To use an enum that I have created
public enum PaymentType {
MC,
VISA,
AMEX,
TELECHECK,
CASH,
ACH }
I've tried this:
switch (Enum.Parse(typeof(PaymentType),salesOrderPayment.PaymentCardKey.ToUpper()))
but get red squiggly lines and when I hover over it says "A value of an integral type expected".

Try this:
switch ((PaymentType)Enum.Parse(typeof(PaymentType),salesOrderPayment.PaymentCardKey,true)))
Notice the cast to PaymentType type, also note that your switch cases has to be enum fields rather than strings.
I've used another overload of Enum.Parse which takes bool ignoreCase as parameter, make use of it so that you don't need ToUpper call.

As the Enum.Parse method returns with an Object (see here), you will need to cast the result of Enum.Parse to PaymentType.

Related

if string value is used in case then we not need to convert there format before comparison?

I have used below code in a project and someone ask me to use ToLower() or ToUpper() and I think it is unnecessary.
public somefun(Classabc clsabc, string emptype, string id)
{
switch(emptype)
{
case :"AnyInput":
{
//do
}
break;
case :"StringInput":
{
//do
}
break;
}
}
if(emptype=="AnyInput")
{
///
}
Is the above perfect or we need to use ToLower() or ToUpper() with empType in if()? Is there any issue or programming rule violation with my code? According to me in case (switch) we are using email type as constant for case matching and if emptype value can be used in case matching then there is no need to add extra functions to convert to there case before string matching.
Depends on what you guys are looking for.
If the comparison is case sensitive, you can keep the switch-case comparison like you did in the example you provided.
In case the comparison is insensitive, you can pattern matching (C# 7 and above) and write something like this:
switch (true)
{
case bool b when emptype.Equals("AnyInput", StringComparison.InvariantCultureIgnoreCase):
// do
break;
case bool b when emptype.Equals("StringInput", StringComparison.InvariantCultureIgnoreCase):
// do
break;
default:
break;
}

String.Empty in Switch/case statement generate a compiler error

If String.Empty is as good as "", then how come the compiler throws up with string.Empty in the case statement? Nothing can be more constant than string.Empty in my view. Anyone know? Thanks!
switch (filter)
{
case string.Empty: // Compiler error "A constant value is expected"
break;
case "": // It's Okay.
break;
}
You can try like this instead:
switch(filter ?? String.Empty)
string.Empty is a read-only field whereas "" is a compile time constant. You can also go through a article here on Code Project String.Empty Internals
//The Empty constant holds the empty string value.
//We need to call the String constructor so that the compiler doesn't
//mark this as a literal.
//Marking this as a literal would mean that it doesn't show up as a field
//which we can access from native.
public static readonly String Empty = "";
On a side note:
You will also see this issue when you are providing the default parameter value inside your method(C# 4.0):
void myMethod(string filter = string.Empty){}
The above will result in a compile time error as the default value needs to be a constant.
The reason is: you cannot use readonly values in case: consider the following scenario:
public string MyProperty { get; } // is a read-only property of my class
switch (filter)
{
case MyProperty: // wont compile this since it is read only
break;
// rest of statements in Switch
}
As you said string.Empty is equivalent to "", here I can prove this with the same example of a switch statement:
string filter = string.Empty;
switch (filter)
{
case "": // It's Okay.
break;
//rest of statements in Switch
}
Then the only reason it won't allow string.Empty in case it is read-only, the switch won't allow read-only values in its case.

Is it possible to parse "-1.#IND", etc using Double.Parse method

Trying to use System.Double.Parse(string) method for strings such as "-1.#IND" and "INF" representing special values results in a FormatException.
Is there any built-in .NET framework support to parse these?
No, the only non-numeric values double.Parse recognizes are the string values returned by double.Nan.ToString(), double.PositiveInfinity.ToString(), and double.NegativeInfinity.ToString() (dependent on Culture).
In your case I would just use a switch:
double dblValue;
switch strValue
{
case "-1.#IND":
dblValue = double.Nan;
break;
case "INF":
dblValue = double.Infinity;
break;
//... other casess
default:
dblValue = double.Parse(strValue);
break;
}
NaN and other values are parsed in the specified culture (or neutral, if no culture is specified). You can play with those here if you want.
If you have to parse something more special, then just
public double MyParse(string text)
{
if(text == "blablabla")
return double.NaN;
if(text.Contains("blablabla")) ...
if(text.StartsWith(...
return double.Parse(text);
}

Using an enum and a switch statement c#

I am using an enum as my options for a switch statement and it works. The problem is if the user enter a non valid option the program crashes. What should I add so that the default is used?
my enum class
public enum Options : byte
{
Display = 1,
Add,
Toggle,
Max,
Mean,
Medium,
Exit
}
in main my switch statement
string volString = Console.ReadLine();
Options options = (Options)Enum.Parse(typeof(Options), volString);
// this is the line that is giving me the runtime error. Since other options are not found
in the enum the program crashes.
switch (options)
{
case Options.Display: //dispaly regular time
case Options.Toggle://toggle
default:
Console.WriteLine("entry blah blah");
break;
Instead of Enum.Parse use Enum.TryParse... this will return a boolean to say if the text can be converted into your enum. If it's true run your switch otherwise inform the user that they entered an invalid string.
Use Enum.TryParse instead:
Options options;
if(!Enum.TryParse(volString, out options)) {
// It wasn't valid input.
}
How about:
Options value;
if(!Enum.TryParse(volString, out value)) // note implicit <Options>
value = Options.SomeDefaultValue;
Look at Enum.TryParse(...) you can use this to check for invalid strings.

String Comparison

Scenario
Consider the following code snippet.
string s = "S";
string s1 = "S";
string s2 = string.Empty;
switch (s)
{
case "S":
s1 = "StringComparison";
break;
default:
break;
}
switch (s[0])
{
case'S':
s2 = "StringCOmpare2";
break;
default:
break;
}
the first switch case, results in a stringcomparison within IL.
But the second switch case, does not result in a stringcomparison within IL.
Can anyone justify this?
Because on the second switch you're are not doing a String comparison, you're doing a Char comparison.
The easiest answer is that you're not doing a string comparison in the second block; you're comparing two characters.
However, you're right in that the two code blocks are functionally equivalent. A good optimizing compiler should be able to detect that 's' is a fixed-length string, and rewrite it not to use a full string comparison.
You're accessing the string via its indexer which returns a char and so lets you use the string as if it was an array of chars.
So whar you're doing is a char comparison. Using the apostrophe for the 'S' also tells you that you're using 'S' as a char and not as a string.
Your second switch statement isn't using a string, but a single char. Hence, no string comparison.

Categories