I have a switch case statements in c#, here all the cases i made as private constants ,is there any bad programming practice going on here, or do i need to use enumeration here and enumerator in case block.Only three constants i showed here, i have ten constants and ten case block
private const String FEASIBLESIZE = "Total FEASIBLESIZE";
private const String AVAILABLESIZE = "Total AVAILABLESIZE";
private const String EXCESSSIZE = "Total EXCESSSIZE";
.
.
switch (value.ToString())
{
case FEASIBLESIZE:
Level.Add(TEAMSIZE, test.ToString());
break;
case AVAILABLESIZE:
Level.Add(BROADSIZE, test.ToString());
break;
case EXCESSSIZE:
Level.Add(NARROWSIZE, test.ToString());
break;
.
.
.
Aside from the horrible formatting it looks roughly okay. Of course that's a bit hard to tell without actually knowing your code. Darin is correct though, in that you're not adhering to the default naming conventions (all caps is a no-go anywhere in C#).
But I have seen much worse, if that's any consolation.
What you are doing looks like something that can be replaced using a Dictionary<string,string> mapping from one size type to another.
var sizeMap = new Dictionary<string,string>();
sizeMap.Add(FEASIBLESIZE, TEAMSIZE);
sizeMap.Add(AVAILABLESIZE, BROADSIZE);
sizeMap.Add(EXCESSSIZE, NARROWSIZE);
And instead of the switch:
Level.Add(sizeMap[value.ToString()], test.ToString());
Please try to scope the case with curly braces this is just individual style but helps when lines of code grows up and also always use the default: too
case FEASIBLESIZE:
{
Level.Add(TEAMSIZE, test.ToString());
break;
}
default:
///...
break;
Your constants appear to be a candidate for Enum, I would go for Enum rather than const here....
Bad Programming Practice:
private const String FEASIBLESIZE = "Total FEASIBLESIZE";
Good Programming Practice:
private const String FEASIBLE_SIZE = "Total FEASIBLESIZE";
Better Programming Practice:
private const String FeasibleSize = "Total FEASIBLESIZE";
Related
I am working on .NET 6.0 application, I have enum that I am trying to use in switch as to compare with string value but getting exception.
error
private static bool ValidateAlphanumericCase(string text, string fieldName)
{
if (!string.IsNullOrWhiteSpace(fieldName))
{
var rule = GetRule(fieldName).TxtFieldFormat; // string value
switch (rule)
{
case TextFieldFormat.AlphanumericUpperCase.ToString():
break;
case TextFieldFormat.AlphanumericLowerCase.ToString():
break;
}
}
else
{
new EmptyFieldNameException();
}
return false;
}
enum
public enum TextFieldFormat
{
AlphanumericUpperCase = 0,
AlphanumericLowerCase = 1,
}
TextFieldFormat.AlphanumericUpperCase.ToString()
This is a method invocation expression and it is not a valid pattern for swith statement.
You can find all valid patterns here: https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/operators/patterns
The closest pattern is type pattern or constant pattern, I guess the compiler recognizes AlphanumericUpperCase as a nested class of TextFieldFormat and fails.
In this case you can use nameof operator.
switch (rule)
{
case nameof(TextFieldFormat.AlphanumericUpperCase):
break;
case nameof(TextFieldFormat.AlphanumericLowerCase):
break;
}
Seems you understood switch-case block a little bit different.
A switch block is simply a shortcut (but more performant shortcut) of many if - else if - else blocks.
Of course they are not the same, but their working logic almost the same.
With this very little info, you can easily think about what's wrong in your code.
Bingo, you're right! Case blocks should check the state. (Boolean value..Just interests with either the given statement results true or false..)
After checking the boolean result, Which case's statement match, code continues on that case block.
So, in your situation your code could be like this :
switch (rule)
{
/// Some statements need to put in paranthesis. Also you would need put business codes of cases into curly braces.
/// I write from my mind.
/// So please try paranthesis and/or braces if this code break.
case rule==TextFieldFormat.AlphanumericUpperCase.ToString():
DoSomethingWithFirstCase(); break;
case rule==TextFieldFormat.AlphanumericLowerCase.ToString():
DoSomethingWitSecondCase(); break;
default: DoSomethingWhenNoMatchWithOtherCases();
}
Hope this helps.
You can also use it this way
TextFieldFormat.AlphanumericUpperCase.ToString("g" or "G")
Can I write switch case in c# like this?
switch (string)
case [a..z]+
// do something
case [A..Z]+
// do something
....
Yes you can in C# 7 (and nobody noticed I had used the incorrect range character in the character class .. instead of -). Updated now with a slightly more useful example that actually works:
using System.Text.RegularExpressions;
string[] strings = {"ABCDEFGabcdefg", "abcdefg", "ABCDEFG"};
Array.ForEach(strings, s => {
switch (s)
{
case var someVal when new Regex(#"^[a-z]+$").IsMatch(someVal):
Console.WriteLine($"{someVal}: all lower");
break;
case var someVal when new Regex(#"^[A-Z]+$").IsMatch(someVal):
Console.WriteLine($"{someVal}: all upper");
break;
default:
Console.WriteLine($"{s}: not all upper or lower");
break;
}
});
Output:
ABCDEFGabcdefg: not all upper or lower
abcdefg: all lower
ABCDEFG: all upper
A minor refinement on David's excellent answer using _ as a discard.
Just a very simple string value as an example.
using System;
using System.Text.RegularExpressions;
public class Program
{
public static void Main()
{
string userName = "Fred";
int something = 0;
switch (true)
{
case bool _ when Regex.IsMatch(userName, #"Joe"):
something = 1;
break;
case bool _ when Regex.IsMatch(userName, #"Fred"):
something = 2;
break;
default:
break;
}
Console.WriteLine(something.ToString());
}
}
Starting with C# 8.0, the answer is now YES!... sort of.
With 8.0, the switch expression was introduced. You can use that to match many different styles of patterns as show below.
string myValueBeingTested = "asdf";
string theResultValue = myValueBeingTested switch
{
var x when
Regex.IsMatch(x, "[a..z]+") => "everything is lowercase",
var y when
Regex.IsMatch(y, "[A..Z]+") => "EVERYTHING IS UPPERCASE",
"Something Specific" => "The Specific One",
_ => "The default, no match scenario"
};
How it works: The switch expression needs a variable that it can feed the results into. The above sample uses theResultValue variable for that. Next you pass into the switch what is referred to as the range expression represented by myValueBeingTested above. The familiar case construct is replaced with a pattern expression followed by the => token and together referred to as an expressionn arm. Anything on the right side of the arm token will end up in the result variable.
Normally the switch expression requires that patterns be a compile-time constant, and you cannot execute arbitrary code inside a switch expression. However we can use a case gaurd pattern by using the when clause to make use of Regex as shown above. Each case needs to be wired up in a distinct arm with distinct throw-away variables, (x and y above).
The 3rd arm shown above is a compile-time constant string to match some specific text if desired. The 4th arm shown above uses the _ pattern, which is a sort of wildcard similar to the old default: keyword. You can also use null instead of, or in addition to _ to handle null cases separately from anything else.
Try it out in my .NET Fiddle sample here.
You should be able to do something like this:
using System.Text.RegularExpressions;
private void fauxSwitch(string caseSwitch)
{
if(Regex.Match(caseSwitch, #"[a..z]+").Success)
{
//do something
return;
}
if(Regex.Match(caseSwitch, #"[A..Z]+").Success)
{
//do something
return;
}
/*default*/
//do something
}
Although, Pattern matching in C#7 is probably the better option.
No. In C# (prior to 7) the switch statement only accepts constant values.
Using more complex expressions as you've suggested is a feature known as 'pattern matching' in the functional programming world.
Pattern matching is included in C#7
Can I put all of this code in one line, like "Level + index ()" Is it possible?
I have this switch function:
switch(index)
{
case 1:
Level1();
break;
case 2:
Level2();
break;
case 3:
Level3();
break;
case 4:
Level4();
break;
case 5:
Level5();
break;
}
as you can see, each index calls a function with the name "Level" and the index number.
Not like that, no. You could use delegates:
// Ideally make this a readonly field.
Action[] actions = { Level1, Level2, Level3, Level4, Level5 };
...
actions[index - 1]();
Or you could use reflection, as others have mentioned... but I'd try to avoid that if possible, especially if performance is a concern.
It does feel like an odd design though - I'd take a step back and consider whether there's a cleaner way of designing this to start with. (It's hard for us to help with that at the moment without more context.)
Try this:
typeof(yourClassCOntainingLevel1Method).GetMethod("Level"+index).Invoke(this,null);
yourClassCOntainingLevel1Method is a class name where you have Level1 method
if it's in the same class as calling:
typeof(this).GetMethod("Level"+index).Invoke(this,null);
The only way to achieve this is through Reflection. But it would be better to have a single Level function that takes the level as parameter:
public void Level(int number)
{
...
}
Please try with the below code snippet.
Type thisType = this.GetType();
MethodInfo theMethod = thisType.GetMethod("Level"+index);
theMethod.Invoke(this, userParameters);
I think the best way is delegate which is answered by Jon Skeet. Also we can try using reflection but it's not the best practice due performance hit.
This kind of code would normally work in PHP, but since the scope is much more strict in C#, it's not. I can't figure out a way to write this code without repeating myself.
static double Cube()
{
Console.Write("Enter the side length of the cube: ");
try
{
double x = Convert.ToDouble(Console.Read());
return Math.Pow(x, 3);
}
catch (FormatException)
{
Console.WriteLine("Invalid input, please enter a number.");
Cube();
}
return 1;
}
..Later in Main():
switch (choice)
{
case 0:
return;
case 1:
double final = Cube();
break;
default:
Console.WriteLine("Please enter 0 or 1.");
Main();
break;
}
Console.WriteLine("The volume is: {0}", Convert.ToString(final));
The Cube() method works fine, but it's messy in my opinion (return 1 at the end to make the compiler happy). But an error comes up saying The name 'final' does not exist in the current context. It can't find final. So the only way to make this work that I'm seeing is to put the Console.WriteLine statement right after the double final = Cube().
I've also tried declaring double final; outside the switch, then just setting final inside each case, but that hasn't worked either.
Thanks!
You're right: this is a mess. Start over.
Your fundamental problem is that you're not separating your concerns. You have a method that does user input, input validation, retry logic and math all at the same time. You should rather make methods for each.
Also, use TryParse to handle the failure case, not exception handling.
Finally, recursion is completely the wrong tool to use. A problem must have the following characteristics to be solved by recursion:
A trivial base case.
Can be reduced to a set of smaller problems.
Solutions to smaller problems can be combined to solve larger problems.
Making a problem smaller repeatedly eventually gets to the trivial case.
Your problem has none of these properties, so recursion is automatically the wrong tool. The tool you want is a loop.
static void Main()
{
double x = ObtainDoubleFromUser(
"Enter the side length of the cube: ",
"Please enter a number: ");
Console.WriteLine("The volume is {0}", Cube(x));
}
static double ObtainDoubleFromUser(string firstMessage, string failureMessage)
{
Console.Write(firstMessage);
while(true)
{
double result;
if (Double.TryParse(Console.Read(), out result))
return result;
Console.Write(failureMessage);
}
}
static double Cube(double x)
{
return Math.Pow(x, 3);
}
Does that all make sense? You want to avoid recursion and exception handling if you possibly can. And keep your concerns separated.
If you want to access final from outside the switch scope, you'll have to declare it outside that scope too. If you reference final and there are code paths that allow not setting a value to final, then the compiler will be "angry".
In php, final would magically be 0 when you don't assign anything to it. Try declaring final before the switch, and then assign a value to it at each case statement including the default case.
Place the variable declaration before your switch statement:
double final = 0.0;
switch(choice)
{
...
}
Then just use the variable in your switch statement:
case 1:
final = Cube();
break;
In C#, variables must be declared before they can be used. In your code, the declaration was limited to the scope of the switch statement. Declaring the variable prior to the switch statement ensures that its in the scope of the method, allowing it to be used inside and after the switch statement.
HI, I've got a simple question, but one that has been bugging me for a while.
Question:
When using switch statements in C#, is it considered better practice to use enums over constants or vice versa? Or is it a matter of preference? I ask this because many people seem to like using enums, but when you are switching on an int value, you have to cast each of the values contained in the enum to an int, even if you specify the type of enum.
Code Snippet:
class Program
{
enum UserChoices
{
MenuChoiceOne = 1,
MenuChoiceTwo,
MenuChoiceThree,
MenuChoiceFour,
MenuChoiceFive
}
static void Main()
{
Console.Write("Enter your choice: ");
int someNum = int.Parse(Console.ReadLine());
switch (someNum)
{
case (int)UserChoices.MenuChoiceOne:
Console.WriteLine("You picked the first choice!");
break;
// etc. etc.
}
}
}
Is there some way you can create an instance of the enum and just cast the whole enum to an int?
Thanks!
Why not do this instead?
UserChoices choice = (UserChoices)int.Parse(Console.ReadLine());
switch (choice)
{
case UserChoices.MenuChoiceOne:
// etc...
Then you only need to cast once.
Update: fixed bug in code!
I think the preference of enums over constants is because of readability and not because of performance. I find it easier to read enums in code (in general and not just in switch statements), than to read/understand constants and their usage.
and btw, you don't have to cast every case, you can just cast your switch.
switch((UserChoices)someEnum)
{
...
I believe you can simply do:
switch((UserChoices)someNum)
{
case UserChoices.MenuChoiceOne:
break;
default:
throw Exception // whatever here
}