Calling a function using a parameter in it's name - c#

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.

Related

Better If statement with type checking C#

I'm currently working on a .NET 4.7.1 application. I have an If-statement to check the data type and call an handler method accordingly.
My current If statement looks like this:
// object msg = MyHelper.Deserialize(xmlString);
if (msg is Tomato) Handle_Tomato((Tomato)msg);
if (msg is Apple) Handle_Apple((Apple)msg);
if (msg is Banana) Handle_Banana((Banana)msg);
if (msg is Orange) Handle_Orange((Orange)msg);
msg is basically an object deserialized from a string.
I was wondering, if there is a better way to write my if statements?
Thank you very much!
As Sweeper mentions in the comments, from C# 7.0 you can use the The is type pattern expression
if (msg is Tomato tomato) Handle_Tomato(tomato);
You could also use pattern matching with a switch statement (Type pattern) since C# 7.0
The type pattern enables concise type evaluation and conversion. When
used with the switch statement to perform pattern matching, it tests
whether an expression can be converted to a specified type and, if it
can be, casts it to a variable of that type.
switch(msg)
{
case Tomato tomato : Handle_Tomato(tomato); break;
case Apple apple : Handle_Apple(apple); break;
...
}
I'd strongly suggest not to do such checks. What if in the future there are dozens of different types? Your if statement will increase and be unmaintainable. What if the type changes? You'd have to change all the if statements as well.
You could solve this by using an interface. You already have the classes.
interface IHandler
{
void Execute();
}
class Orange : IHandler
{
public void Execute()
{
// do your orange stuff
}
}
class Tomato : IHandler
{
public void Execute()
{
// do your tomato stuff
}
}
It can be called like this.
if (msg is IHandler) ((IHandler)msg).Execute();
I think the easiest would be to use a switch/case
switch (msg)
{
case Tomato t:
Handle_Tomato(t);
break;
case Apple a:
Handle_Apple(a);
break;
case Banana b:
Handle_Banana(b);
break;
case Orange o:
Handle_Orange(o);
break;
}
Use a dictionary. I foresee your if will explode with new cases in future, generally speaking, walls of if and large switch statements are bad code. In a similar situation I created something like this:
private static readonly Dictionary<RuntimeTypeHandle, Action<object>> handleMsgImplementations = new Dictionary<RuntimeTypeHandle, Action<object>>
{
{ typeof(Tomato).TypeHandle, x => Handle_Tomato((Tomato)x) },
// etc...
};
// Then instead of if, use this (prepare a catch for Invalid Key or use a TryGetValue)
handleMsgImplementations[msg.GetType().TypeHandle](msg);
I get TypeHandle because I like to use a value type for the key.
EDIT: #TheGeneral answer is the best, also, the C# compiler creates a dictionary under the hood when the amount cases starts to damage performance. I keep my answer because I believe adds value.

Switch Statement with Enum - Or (||) and (&&)

I'm making a project and I have a question. I have 3 enum states like this:
enum GameLevel
{
Level1,
Level2,
None,
}
There's a part in my code where I want to check if there's any level selected or none, so I wanted to do something like:
case !GameLevel.None
or
case GameLevel.Level1 || GameLevel.Level2
Is This Possible?
Various options:
Use switch with a default:
switch (level)
{
case GameLevel.None:
// Whatever
break;
default:
// Do something else
// break
}
Use switch with explicit cases:
// Note: if you add a Level3, you'd need to change this...
switch (level)
{
case GameLevel.Level1:
case GameLevel.Level2:
// Whatever
break;
}
Use an if statment:
if (level != GameLevel.None)
{
...
}
Switch is not used to get a "its not the case"-case. However you can use the default: case, which always executes, when the other cases are "false".
For your !GameLevel.None better use an if case. if(selectedGameLevel != GameLevel.None) { }
I believe the choice of assignment should be based on how many levels you plan on implementing. For less levels (as shown in your example), I would use if and else if as opposed to using switch. Switch only works better if there are more options, as it is then performed differently for faster execution. Jon Skeet's answer will guide you on how to implement the choice you make.

How to use switch case block in c# properly?

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";

Refactor switch statement that assigns different variables depending on case?

How can I refactor a switch statement that is in multiple places in code that assigns a value to a variable depending on which case is thrown, for example:
int a = 0;
int b = 0;
switch(c)
{
case "1"
a = 1;
break;
case "2"
b = 2;
break;
}
In the above example, resharper will use one of the variables as the return and the other as an out parameter. Is there another way to do it, maybe not extracting out the whole switch block.
This code block has a couple of different ways of refactoring it to make it more reusable without having it copied over in places. However, they're going to require reworks of things:
Are the objects logically grouped somehow?
If so, then you could make an object to represent them, and then refactor to return the object set with values.
var myObj = SetObjectAccordingTo(c);
protected SomeObj SetObjectAccordingTo(string c)
{
var myObj = new SomeObj();
switch(c)
{
case "1": myObj.a = 1;
break;
case "2": myObj.b = 2;
break;
}
return myObj;
}
If they are not logically grouped, and each is assigned a value...
Then logic for determining each value needs to be split.
a = DetermineValueForA(c);
b = DetermineValueForB(c);
And each method deals only with the cases where a is involved.
If they are not logically grouped, and only certain values are assigned...
Then there is not much optimization that can be performed save moving the respective values to member variables and then calling each with that specific method.
If you could provide a sample of what you're trying to do, we could offer a solution more than likely.
You mean you'd like to extract this as a method? You might consider returning a struct (or perhaps a class) if A and B are related in some manner. Perhaps, NDA permitting, you could show us a code fragment in context so it might become clearer how to solve this.

using switch statements with constants or enumerations? (Which is better)? C#

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
}

Categories