Switch on one true expression c# - c#

I would have liked to do something like
switch(true) {
case box1.Checked:
do_something(); break;
case box2.Checked:
do_something_else();
and_some_more(); break;
default:
complain_loudly();
}
But that is not allowed in c#; it is in php.
Is there a neater way, besides a
if (box1.Checked) {
do_something();
} else if (box2.checked)
...
?

With C# 7 using case with when. See also The case statement and the when clause
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
Box box1 = new Box();
Box box2 = new Box();
box2.Checked = true;
switch (true)
{
case true when box1.Checked:
Console.WriteLine("box1 is checked");
break;
case true when box2.Checked:
Console.WriteLine("box2 is checked");
break;
default:
Console.WriteLine("neither box checked");
break;
}
return;
}
}
class Box
{
public bool Checked = false;
}
}
Output:
box2 is checked

I would try something like this - find fist checked checkbox from collection and then switch-case by name of checked control...
Something like this:
var checkedCb = this.Controls.OfType<CheckBox>().Where(c => c.Checked).First();
switch (checkedCb.Name)
{
case "cbOne":
break;
case "cbTwo":
break;
default:
break;
}

PHP seems to resolve a switch differently than C#.
In C# you switch over an expression and use the cases to define possible constant results of the expression you switched over. The neat thing about the C# switch is that it might be optimized which requires the cases to be constant expressions.
Your first Problem is that your cases are not constant.
As a result of point 1: If both of your checkboxes are checked which one should be executed? This is a problem that would cause a runtime issue and cannot be evaluated at compile time. C# will not allow multiple cases of the same value.
I don't want to provide any examples of optimization here, simply because I would tell a lot of lies. If you want to know more about these optimizations you may read up to Eric Lipper's blog post about it:
https://blogs.msdn.microsoft.com/ericlippert/2009/06/11/what-does-the-optimize-switch-do/
As a solution: KISS
Keep it simple stupid - meaning - use an if else.
EDIT:
I don't think it adds to readability nor simplicity of your code. This is basically just me trying to do something weird like the switch statement you know from PHP. Please don't use it. I wouldn't recommend using it.
(It takes more space and time, initially and during each call, than a simple if else)
public partial class MainWindow : Window
{
private CheckBox[] _checkboxes;
private Dictionary<int, Action> _checkboxActions = new Dictionary<int, Action>();
public MainWindow()
{
InitializeComponent();
List<CheckBox> checkboxes = new List<CheckBox>();
checkboxes.Add(CheckBox1);
checkboxes.Add(CheckBox2);
_checkboxes = checkboxes.ToArray();
_checkboxActions.Add(CheckBox1.GetHashCode(), OnCheckBox1Checked);
_checkboxActions.Add(CheckBox2.GetHashCode(), OnCheckBox2Checked);
}
public void InvokeCheckboxActions()
{
Action action;
foreach(var checkbox in _checkboxes)
{
if(checkbox.IsChecked == true)
{
int checkboxPtr = checkbox.GetHashCode();
if(_checkboxActions.TryGetValue(checkboxPtr, out action))
{
action();
}
}
}
}
private void OnCheckBox1Checked()
{
Console.WriteLine("Checkbox 1 was checked");
}
private void OnCheckBox2Checked()
{
Console.WriteLine("Checkbox 2 was checked");
}
}

I think this code will have desired behavior.
public enum Mode { None, Break, Continue };
public sealed class Branch<T>
{
public Mode Mode { get; }
public T Value { get; }
public Action Action { get; }
public Branch(T value, Action action, Mode mode = Mode.None)
{
Value = value;
Action = action;
Mode = mode;
}
}
public static class CaseHelper
{
public static void Switch<T>(T condition, params Branch<T>[] branches)
{
bool Continue = false;
foreach (var branch in branches)
{
if (branch.Value.Equals(condition) || Continue)
{
branch.Action();
}
if (branch.Mode == Mode.Break) break;
Continue = branch.Mode == Mode.Continue;
}
}
}
usage:
CaseHelper.Switch(true, new Branch<bool>(box1.Checked, doSomething1), new Branch<bool>(box2.Checked, () => doSomething2()));
but it looks not very elegant
P.S.:
We can add implicit conversion operator to Branch
public static implicit operator Branch<T>(Tuple<T, Action, Mode> triple)
{
return new Branch<T>(triple.Item1, triple.Item2, triple.Item3);
}
public static implicit operator Branch<T>(Tuple<T, Action> duple)
{
return new Branch<T>(duple.Item1, duple.Item2);
}
and use something like this:
CaseHelper.Switch(true,
(Branch<bool>)Tuple.Create<bool, Action>(box1.Checked, doSomething1),
(Branch<bool>)Tuple.Create<bool, Action, Mode>(box2.Checked, () => doSomething2(), Mode.Break)
);

Related

Enumerate specific type of members by a inherited constructor

I'm trying to make a menu for a console, and I have this code:
public class Option { /* Id, Name, & constructor */ }
public abstract class Menu {
protected const int rawId = 0;
protected Menu() {
int i = 0;
// CS1579: foreach statement cannot operate on variables of type 'Menu.Menu' because 'Menu.Menu' does not contain a public instance definition for 'GetEnumerator'
foreach (Option o in this) { o.Id = ++i; } // Assigns an id to each option in inherited menus
}
}
public class MMain:Menu {
Option OpenFile = new Option(rawId, "Open File");
Option ExitProgram = new Option(rawId, "Terminate Program");
public MMain():base() { }
}
int Prompt(/* menu to be displayed */) { /* List options; Return selected by id }
So that in the main program, I can do this:
switch (Prompt(/* MMain this case */)) {
case MMain.OpenFile.Id: { /* Opens A File */ break; }
case MMain.ExitProgram.Id: { /* Exits */ break; }
}
Problem is, this in foreach needs a GetEnumerator thing, which I failed to enumerate Options from both the base and the inherited class. Lack of Option should return at least an empty object.
I'm avoiding:
string comparison with switch (hurts efficiency, so I introduced id)
use of enum (tried it, cannot be used as parameters for function, made a mess)
tailoring a function for each menu (hard to maintain, kills consistency)
Is there any way to accomplish this?
Unsuccessful Approach with enum (bg info)
Fine to ignore. Included in case being asked to try enum, tried this:
public class MMain {
public enum Option { OpenFile, ExitProgram /* and more */ }
public static string NameOf(Option o) {
return o switch {
Option.OpenFile => "Open File",
Option.ExitProgram => "Terminate Program",
_ => throw new ArgumentException(InvMO)
};
}
public static Option Prompt() {
ListOptions(typeof(Option));
/* return Choice(...); */
}
private static void ListOptions(Type t) {
foreach (var option in Enum.GetValues(t)) {
// CS1503: cannot convert from 'object' to 'Option'
Console.WriteLine(NameOf(option));
/* Also if casting like this: Console.WriteLine((t)NameOf(option))
it will give CS0118: 't' is a variable but is used like a type */
}
}
}
and this:
/* ... */
public static Option Prompt() {
Option opts;
ListOptions(opts); // Unable to declare a function that inputs all types of enum
/* ... */
So that in the main program:
switch (MMain.Prompt()) {
case MMain.Option.OpenFile: { /* Opens A File */ break; }
case MMain.Option.ExitProgram: { /* Exits */ break; }
}
Credits
Guidance of my code as follows:
Associating enums with strings in C#, source of the whole idea for replacing enum, really
Constructor inheritance
For the enum approach:
class EnumLoop<Key> where Key : struct, IConvertible, felt it was so close but eventually didn't work it out myself, therefore gave up enum
foreach (Suit suit in (Suit[]) Enum.GetValues(typeof(Suit))), cannot pass enum hence cannot create Option opt in (Option[])Enum.GetValues(typeof(Option)))
Creating variable with System.Type (Passing typeof(Option) to a function, to create Option opt in the function, unable to work it out too)
I don't know if I understand your question very well, but this problem could be worked around using reflections, or, a much easier approach, working as a list of options within the menu, like this:
using static MMain;
var main = new MMain();
switch ((MMainOptions)main.Prompt())
{
case MMainOptions.OpenFile:
Console.WriteLine($"Chosen option: Open file");
break;
case MMainOptions.TerminateProgram:
Console.WriteLine($"Chosen option: Terminate program");
break;
}
Console.ReadKey();
public class Option
{
public int Id { get; set; }
public string Name { get; set; }
public Option(int id, string name)
{
Id = id;
Name = name;
}
public Option() { }
}
public abstract class Menu
{
protected List<Option> Options { get; set; }
protected Menu()
{
Options = new List<Option>();
}
public int Prompt()
{
Console.WriteLine("{0,2}{1,2}", "Id", "Name");
foreach (var option in Options)
{
Console.WriteLine("{0,2}{1,2}", option.Id, , option.Name);
}
Console.WriteLine("Type id:");
var result = Console.ReadLine();
return Convert.ToInt32(result);
}
}
public class MMain : Menu
{
public enum MMainOptions
{
OpenFile = 1,
TerminateProgram = 2
}
public MMain() : base()
{
Options.Add(new Option((int)MMainOptions.OpenFile, "Open File"));
Options.Add(new Option((int)MMainOptions.TerminateProgram, "Terminate Program"));
}
}
Hope this helps

Determining the correct function to call based on parameter

Here's my scenario:
I have ~100,000 string[] going into a function called CallCommand(string[] command).
I have ~50 static classes, that all contain the same method: public static void ParseCommand(string[] command).
My CallCommand function checks the first parameter of the string[] and calls the correct class's ParseCommand.
I'm trying to find a way to call the right function automatically (using generics?) without a switch statement.
Currently, I'm using a large switch statement like so (only showing a few since there are ~50):
public static void CallCommand(string[] command)
{
string commandVerb = command.First().ToLower();
switch (commandVerb)
{
case "add":
AddCommand.ParseCommand(command);
break;
case "attach":
AttachCommand.ParseCommand(command);
break;
case "assign":
AssignCommand.ParseCommand(command);
break;
case "cancel":
RunCommand.ParseCommand(command);
break;
case "center":
CenterCommand.ParseCommand(command);
break;
case "complain":
ComplainCommand.ParseCommand(command);
break;
default:
Log("This command doesn't exist.");
break;
}
}
I wanted to reduce the code a bit, so I tried using a Dictionary<string, Action> instead (again, reduced the number of key/value pairs here since there's ~50):
private static readonly Dictionary<string, Action<string[]>> handlers = new Dictionary<string, Action<string[]>
{
["add"] = new Action<string[]>(AddCommand.ParseCommand),
["assign"] = new Action<string[]>(AssignCommand.ParseCommand),
["attach"] = new Action<string[]>(AttachCommand.ParseCommand),
["cancel"] = new Action<string[]>(AddCommand.ParseCommand),
["center"] = new Action<string[]>(AddCommand.ParseCommand),
["complain"] = new Action<string[]>(ComplainCommand.ParseCommand)
};
Here's the CallCommand function after setting up the dictionary:
public static void CallCommand(string[] command)
{
string commandVerb = command.First().ToLower();
handlers[commandVerb].Invoke(command);
}
Finally, here's an example of one of my static classes. They are all set up exactly the same way. They just do different things in their ParseCommand method:
public static class AssignCommand
{
public static void ParseCommand(string[] command)
{
//do stuff with command
}
}
I understand I would have to refactor my static classes a bit to achieve what I want (if it's possible), I've just been unable to figure out the correct way.

How to clean up if else series

Work in C#, want to reduce if else series, entity have two property FromServiceID and ToServiceID ,suppose my ServiceClass instance have bellow information.How to clean up bellow code? any type of suggestion will be acceptable.
entity= new ServiceClass();
entity.FromServiceID=3
entity.ToServiceID=1
if (entity.FromServiceID == 1)
{
entity.1KWithdrawal();
}
else if (entity.FromServiceID == 2)
{
entity.10KWithdrawal();
}
else if (entity.FromServiceID == 3)
{
entity.BTWithdrawal();
}
if (entity.ToServiceID == 1)
{
entity.1KDeposit();
}
else if (entity.ToServiceID == 2)
{
entity.10KDeposit();
}
else if (entity.ToServiceID == 3)
{
entity.BTDeposit();
}
public class ServiceClass
{
public int FromServiceID { get; set; }
public int ToServiceID { get; set; }
public void 1KWithdrawal()
{ Console.WriteLine("One_KWithdrawal"); }
public void 10KWithdrawal()
{ Console.WriteLine("Ten_KWithdrawal"); }
public void BTWithdrawal()
{ Console.WriteLine("BTWithdrawal"); }
public void 1KDeposit()
{ Console.WriteLine("One_KDeposit"); }
public void 10KDeposit()
{ Console.WriteLine("Ten_KDeposit"); }
public void BTDeposit()
{ Console.WriteLine("Ten_KDeposit"); }
}
Use a Dictionary. Something like this:
Dictionary<int, ServiceClass> dictionary = new Dictionary<int, ServiceClass>()
{
{1, new ServiceClass()},
{2, new ServiceClass()},
{3, new BTWithdrawal()},//assume BTWithdrawal inherits from ServiceClass
};
An example of how using it:
ServiceClass value=new ServiceClass();
value.FromServiceId=1;
value.ToServiceId = 2;
dictionary.TryGetValue(value.FromServiceId, out value);
//or dictionary.TryGetValue(value.ToServiceId, out value);
if (value != null) MessageBox.Show(value.Id.ToString());
Maybe this is an overkill, but you can create a class for each one of your cases that inherits from a common interface (let's call it ICommon) that exposes a common method for each case (in your case a Create method) and then inject that interface in the constructor of ServiceClass.
Then when you want to use ServiceClass, you will have to provide an actual implementation of ICommon (one of the classes you extracted from each case) and finally you only have to call entity.Create.
I believe this is the strategy pattern, that in summary says that you should extract an algorithm in a different class under a common interface.
Finally, this refactoring will reduce the cyclotomic complexity of your code (this mainly means that you reduce the branching on your code) which always a good thing.
What you could do is to put all the variations into an enum and call the enum values exactly like your methods that you would like to call. (I would suggest not to use numbers in the name, since the compiler won't allow it)
For the sake of simplicity and testability I put the enum and the methods into the same class:
public class ServiceClass
{
public enum ServiceID
{
OneKWithdrawal,
Ten_KWithdrawal,
BTWithdrawal,
OneKDeposit,
Ten_KDeposit,
BTDeposit
}
public ServiceID From_Ser_ID { get; set; }
public ServiceID To_Ser_ID { get; set; }
public void One_KWithdrawal()
{ Console.WriteLine("One_KWithdrawal"); }
public void Ten_KWithdrawal()
{ Console.WriteLine("Ten_KWithdrawal"); }
public void BTWithdrawal()
{ Console.WriteLine("BTWithdrawal"); }
public void One_KDeposit()
{ Console.WriteLine("One_KDeposit"); }
public void Ten_KDeposit()
{ Console.WriteLine("Ten_KDeposit"); }
}
This would be the method that would execute your if-condition methods. It uses reflection to access the methods that are coded in the enum. You probably have to adjust the object parameter in the Invoke(sc, null); call depending on where your methods are situated. If they are in the same class as where you would call execute you can use this.
public static void execute(ServiceClass sc)
{
sc.GetType().GetMethod(sc.From_Ser_ID.ToString()).Invoke(sc, null);
sc.GetType().GetMethod(sc.To_Ser_ID.ToString()).Invoke(sc, null);
}
And here you can test the entire code:
public static void Main(string[] args)
{
ServiceClass entity = new ServiceClass();
entity.From_Ser_ID = ServiceClass.ServiceID.BTWithdrawal;
entity.To_Ser_ID = ServiceClass.ServiceID.Ten_KDeposit;
execute(entity);
}
So you would end up with an enum and 2 lines of code.
You can use switch case as below:
var entity = new ServiceClass();
entity.FromServiceID = 3;
entity.ToServiceID = 1;
switch(entity.FromServiceID)
{
case 1:
new 1KWithdrawal();
break;
case 2:
new 10KWithdrawal();
break;
case 3:
new BTWithdrawal();
break;
}
switch(entity.ToServiceID)
{
case 1:
new 1KDeposit();
break;
case 2:
new 10KDeposit();
break;
case 3:
new BTDeposit();
break;
}

Call a method dynamically based on some other variable [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
How to Call method using its name?
Getting sick of using switch/case statements. I'm wondering if there is some way to call a method based on the value provided by the user. Understand that there could be a million reasons why this is a bad idea, but here's what I'm thinking:
Console.Write("What method do you want to call? ");
string method_name = Console.ReadLine();
then somehow call the method contained in 'method_name'. Is this even possible?
You can use reflection:
var type = typeof(MyClass);
var method = type.GetMethod(method_name);
method.Invoke(obj, params);
If you want the type to be dynamic as well as the method then use this instead of typeof(MyClass):
var type = Type.GetType(type_name);
Many times you can refactor switch statements to dictionaries...
switch (caseSwitch)
{
case 1:
Console.WriteLine("Case 1");
break;
case 2:
Console.WriteLine("Case 2");
break;
case 3:
Console.WriteLine("Case 3");
break;
}
can become ...
var replaceSwitch = new Dictionary<int, Action>
{
{ 1, () => Console.WriteLine("Case 1") }
{ 2, () => Console.WriteLine("Case 2") }
{ 3, () => Console.WriteLine("Case 3") }
}
...
replaceSwitch[value]();
This is a very subtle shift that doesn't seem to gain much, but in reality it's much, much better. If you want to know why, this blog post explains it very well.
Instead of reflection, if you have to act on the user's input value w/o using switch statement, you could use a dictionary having the list of methods mapped against the input value.
private static void Method1(int x)
{
Console.WriteLine(x);
}
private static void Method2(int x)
{
}
private static void Method3(int x)
{
}
static void Main(string[] args)
{
Dictionary<int, Action<int>> methods = new Dictionary<int, Action<int>>();
methods.Add(1, Method1);
methods.Add(2, Method2);
methods.Add(3, Method3);
(methods[1])(1);
}
Your sample
public class Boss
{
public void Kick()
{
Console.WriteLine("Kick");
}
public void Talk(string message)
{
Console.WriteLine("Talk " + message);
}
public void Run()
{
Console.WriteLine("Run");
}
}
class Program
{
static void AutoSwitch(object obj, string methodName, params object[] parameters)
{
var objType = typeof(obj);
var method = objType.GetMethod(methodName);
method.Invoke(obj, parameters);
}
static void Main(string[] args)
{
var obj = new Boss();
AutoSwitch(obj, "Talk", "Hello World");
AutoSwitch(obj, "Kick");
}
}
Another interesting way I have seen to handle(read avoid) switch statements differently is to use a dictionary of methods. I stole this from http://www.markhneedham.com/blog/2010/05/30/c-using-a-dictionary-instead-of-if-statements/ and it looks like they are using the MVC framework but the same basic principal applies
public class SomeController
{
private Dictionary<string, Func<UserData,ActionResult>> handleAction =
new Dictionary<string, Func<UserData,ActionResult>>
{ { "Back", SaveAction },
{ "Next", NextAction },
{ "Save", SaveAction } };
public ActionResult TheAction(string whichButton, UserData userData)
{
if(handleAction.ContainsKey(whichButton))
{
return handleAction[whichButton](userData);
}
throw Exception("");
}
private ActionResult NextAction(UserData userData)
{
// do cool stuff
}
}
If you're thinking you could somehow do this:
Console.Write("What method do you want to call? ");
string method_name = Console.ReadLine();
method_name();
You are mistaken. You have to analyze the user input and call a method based on that.
Sure, reflection is your friend. Have a look at Type.GetMethod().

Dynamic method dispatch based on value of variable

Long switch statments are often frowned upon. The solution is to use polymorphism. However what if the thing I'm switching on is not a type code? What I would like to do is replace the switch statement with something like this...
public void HandleString(string s = "Hello")
{
...
}
public void HandleString(string s = "Goodbye")
{
...
}
...
HandleString("Hello"); // results in the first method being called.
This would replace the following...
string s = "Hello";
switch(s)
{
case "Hello":
...
break;
case "Goodbye":
...
break;
default;
break;
}
Any ideas? In theory I think you could do away with 'if/switch' statements altogether and just call methods that are automatically bound based on the value of an expression.
If you have a large number of options, and high possibility that there will be more in the future - or you just need to system to be easily extensible - then you can always use an explicit dispatch table:
Dictionary<string, Action<string>> actions =
new Dictionary<string, Action<string>>()
{
{ "Hello", HandleHello },
{ "Goodbye", HandleGoodbye }
};
private static void HandleHello(string s) { ... }
private static void HandleGoodbye(string s) { ... }
...
actions[s](s);
You can also provide a way to extend the table by allowing external clients of your API to register their own handler for a given string.
There are languages that implement that sort of semantics. One that I'm familiar with is the compiler generator tool called Elegant from Phillips.
In a language like this, a simple factorial algorithm might look like:
fact (value : Int) : Int
conditions value < 0
{
{ "Illegal input value\n" } astype Message
return 0
}
fact (value = 0) : Int
{
return 0
}
fact (value = 1) : Int
{
return 1
}
fact (value : Int) : Int
{
return value * fact(value - 1);
}

Categories

Resources