Add or subtract two numbers depending on dropdown selection Announcing the arrival of Valued Associate #679: Cesar Manara Planned maintenance scheduled April 17/18, 2019 at 00:00UTC (8:00pm US/Eastern)Implementing a collection class to represent a Path of SegmentsAdd/subtract questions gameFinding patterns in a growing collection“Fancy-pants” vs “Cowboy” codingDoes this unusual data access pattern create any problems?Sprite animation handlerDecoration Freak, or OCP in action?Dynamically adding controls to a form in a WinForms projectBuilding a data tree out of a text file C#Bash Script for file auditing, push information to server and be able to view in a web page

Jazz greats knew nothing of modes. Why are they used to improvise on standards?

90's book, teen horror

How do I automatically answer y in bash script?

How to say 'striped' in Latin

What is the electric potential inside a point charge?

Stop battery usage [Ubuntu 18]

What do I do if technical issues prevent me from filing my return on time?

Cold is to Refrigerator as warm is to?

I'm having difficulty getting my players to do stuff in a sandbox campaign

Can I add database to AWS RDS MySQL without creating new instance?

What can I do if my MacBook isn’t charging but already ran out?

What are the performance impacts of 'functional' Rust?

How does modal jazz use chord progressions?

Need a suitable toxic chemical for a murder plot in my novel

How to market an anarchic city as a tourism spot to people living in civilized areas?

Statistical model of ligand substitution

How to set letter above or below the symbol?

When is phishing education going too far?

How to politely respond to generic emails requesting a PhD/job in my lab? Without wasting too much time

Single author papers against my advisor's will?

Can a zero nonce be safely used with AES-GCM if the key is random and never used again?

The following signatures were invalid: EXPKEYSIG 1397BC53640DB551

How do I keep my slimes from escaping their pens?

New Order #5: where Fibonacci and Beatty meet at Wythoff



Add or subtract two numbers depending on dropdown selection



Announcing the arrival of Valued Associate #679: Cesar Manara
Planned maintenance scheduled April 17/18, 2019 at 00:00UTC (8:00pm US/Eastern)Implementing a collection class to represent a Path of SegmentsAdd/subtract questions gameFinding patterns in a growing collection“Fancy-pants” vs “Cowboy” codingDoes this unusual data access pattern create any problems?Sprite animation handlerDecoration Freak, or OCP in action?Dynamically adding controls to a form in a WinForms projectBuilding a data tree out of a text file C#Bash Script for file auditing, push information to server and be able to view in a web page



.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty margin-bottom:0;








8












$begingroup$


I have a drop down list contain "Add" and "Subtract". When user select either one, it will call a function Calculate()



private int Calculate(string sAction)

int iTotal = 0;

if(sAction == "Add")

iTotal = X + Y;

else if(sAction == "Subtract")

iTotal = X-Y;


return iTotal;



I do not wish to hard coded it to compare the action. It seem like not fulfill Open Closed Principle. If I change the text in the drop down list, I need to change the function as well. May I know how I can improve this code?










share|improve this question











$endgroup$







  • 7




    $begingroup$
    Defensive programming tip: Add a final else with exception in case the input is neither 'Add' or 'Substract'.
    $endgroup$
    – Aphelion
    Oct 10 '17 at 7:22

















8












$begingroup$


I have a drop down list contain "Add" and "Subtract". When user select either one, it will call a function Calculate()



private int Calculate(string sAction)

int iTotal = 0;

if(sAction == "Add")

iTotal = X + Y;

else if(sAction == "Subtract")

iTotal = X-Y;


return iTotal;



I do not wish to hard coded it to compare the action. It seem like not fulfill Open Closed Principle. If I change the text in the drop down list, I need to change the function as well. May I know how I can improve this code?










share|improve this question











$endgroup$







  • 7




    $begingroup$
    Defensive programming tip: Add a final else with exception in case the input is neither 'Add' or 'Substract'.
    $endgroup$
    – Aphelion
    Oct 10 '17 at 7:22













8












8








8


1



$begingroup$


I have a drop down list contain "Add" and "Subtract". When user select either one, it will call a function Calculate()



private int Calculate(string sAction)

int iTotal = 0;

if(sAction == "Add")

iTotal = X + Y;

else if(sAction == "Subtract")

iTotal = X-Y;


return iTotal;



I do not wish to hard coded it to compare the action. It seem like not fulfill Open Closed Principle. If I change the text in the drop down list, I need to change the function as well. May I know how I can improve this code?










share|improve this question











$endgroup$




I have a drop down list contain "Add" and "Subtract". When user select either one, it will call a function Calculate()



private int Calculate(string sAction)

int iTotal = 0;

if(sAction == "Add")

iTotal = X + Y;

else if(sAction == "Subtract")

iTotal = X-Y;


return iTotal;



I do not wish to hard coded it to compare the action. It seem like not fulfill Open Closed Principle. If I change the text in the drop down list, I need to change the function as well. May I know how I can improve this code?







c# beginner






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Oct 10 '17 at 16:09









200_success

131k17157422




131k17157422










asked Oct 10 '17 at 5:44









Derick LooDerick Loo

14613




14613







  • 7




    $begingroup$
    Defensive programming tip: Add a final else with exception in case the input is neither 'Add' or 'Substract'.
    $endgroup$
    – Aphelion
    Oct 10 '17 at 7:22












  • 7




    $begingroup$
    Defensive programming tip: Add a final else with exception in case the input is neither 'Add' or 'Substract'.
    $endgroup$
    – Aphelion
    Oct 10 '17 at 7:22







7




7




$begingroup$
Defensive programming tip: Add a final else with exception in case the input is neither 'Add' or 'Substract'.
$endgroup$
– Aphelion
Oct 10 '17 at 7:22




$begingroup$
Defensive programming tip: Add a final else with exception in case the input is neither 'Add' or 'Substract'.
$endgroup$
– Aphelion
Oct 10 '17 at 7:22










5 Answers
5






active

oldest

votes


















9












$begingroup$

Be sure when you ever have a code that it has the chain of if else there should be an improvement. (even many programmers say you should not use if statement in your code as possible and some others say don't use else statement at all!)



You can use something like this:



First Add a class to manage your actions:



 public class ActionRegistry: Dictionary<string, Func<int, int, int>>

public ActionRegistry()

this.Add("Add", (x, y) => x + y);
this.Add("Subtract", (x, y) => x - y);





Then you can use that class like this:



public class DoStuff

private int Calculate(string sAction)

var actionRegistry= new ActionRegistry();
var a = 1;
var b = 2;
//var actionResult= actionRegistry[this should come from your drop down].Invoke(a, b);
var actionResult= actionRegistry[sAction].Invoke(a, b);


//you can even Register New Action Like this :
actionRegistry.Add("Multiply",(x,y)=>x*y);

//then you can use it somewhere else:
var multiplyResult = actionRegistry["Multiply"].Invoke(a, b);
return actionResult;




Every time your action has changed you just need to add the new action in your ActionRegistry. With this approach, there is no need for that if-else statement.



By the way, you can even use interface and DI to loosely couple the ActionManager.



UPDATE Here my update using enums:



First Declare an Enum :



enum ActionType 

Add,
Subtract



Then use that enum in your ActionRegistry class:



public class ActionRegistry: Dictionary<int, Func<int, int, int>>

public ActionRegistry()

//it's better to register your actions outside the class
// and don't use enum inside your class
// but for simplicity i did that inside the class

this.Add((int)ActionType.Add, (x, y) => x + y);
this.Add((int)ActionType.Subtract, (x, y) => x - y);





then you should change your calculate method like this :



 private int Calculate(int actionTypeCode)

var actionRegistry= new ActionRegistry();
var a = 1;
var b = 2;
//var actionResult= actionRegistry[this should come from your drop down].Invoke(a, b);
var actionResult= actionRegistry[actionTypeCode].Invoke(a, b);

return actionResult;



Note that you should bind your dropdown list with your enum keys as value.
I prefer to use an integer as my key because I can add more item later without changing my enum but it is not necessary.






share|improve this answer











$endgroup$








  • 3




    $begingroup$
    Simple and pragmatic solution :), You could also pass a string comparer to the dictionary's constructor to become a case insensitive dictionary: public ActionManager() : base(StringComparer.InvariantCultureIgnoreCase). How would you handle the case "action not available"?
    $endgroup$
    – JanDotNet
    Oct 10 '17 at 6:49






  • 1




    $begingroup$
    What about instead of using a String as an identifier, why not creating an Enum and then using it? This would put aside problems like aDD instead of Add or subtrat instead of Subtract.
    $endgroup$
    – auhmaan
    Oct 10 '17 at 9:12






  • 1




    $begingroup$
    One of the askers concerns was If I change the text in the drop down list, I need to change the function as well, and I don't see how that is addressed here. If the words in the text box change, this code still has to be revisited manually.
    $endgroup$
    – JPhi1618
    Oct 10 '17 at 14:17






  • 1




    $begingroup$
    This is a good, extensible approach. Just don't call it a Manager (nor Helper, nor Utils). It's an ActionRegistry, or ArithmeticOperations.
    $endgroup$
    – Igor Soloydenko
    Oct 10 '17 at 15:18






  • 1




    $begingroup$
    @JPhi1618 you should read the key and your dropdown list key from one place. you can use an enum or constant or database for that by the way your calculate method won't ever change.
    $endgroup$
    – Pouya Samie
    Oct 10 '17 at 18:18



















7












$begingroup$

Is it worth changing? IMO: Code is best left as-is



It is worth employing some form of polymorphism for one if statement? You gotta be kidding me: for one if statement - to abstract it out? That would make it more complicated, would it not? In my opinion - probably not. cf: @t3chb0t who has a different view.



the code is small and very manageable. if it's already in place and working, and you have no reason to change it, then probably just leave it as is. there's nothing wrong with hard-coded code if it's working and will never change. but if changes start creeping in, then -- and only then consider refactoring. there's no point writing pure OOP for its own sake - perhaps that will make it harder to understand than it is now.



Or if you did want to make it easier to change (slightly), then you could just use an enum. If you change the enum value from “Add” to “Addition” you can ask Visual Studio or Resharper to do all the work for you – but if you wanted to add a new item or decide to get rid of one, then certainly you will be making changes in two places and the open closed principle will be thus violated. Also note how the use of the temporary variables are somewhat more cleaned up below:



internal class Program

enum ListItem Add, Subtract

private int Calculate(ListItem action)

if (action == ListItem.Add)

return 1234; // implement the calculation

else if(action == ListItem.Subtract)

return 1234; // implement the calculation

else

return 1234; // implement the calculation






You could go for a polymorphic solution - as an academic exercise?



You could implement the command design pattern and have a look at the MVVM design pattern (google them) - or other similar polymorphic solution. but you've already written the code!



@PouyaSamie has written a very elegant solution (and it's beautiful in its sophistication) @MartinBeam has a nice answer too. In conclusion my question to you as you read some of the polymorphic solutions - (which are all great - and with the utmost respect to those folks): does it make it easier to understand the code or harder?






share|improve this answer











$endgroup$








  • 6




    $begingroup$
    The code is not best as-is, it's horrible. Everything is hardcoded. You should always bother or otherwise you never learn ;-]
    $endgroup$
    – t3chb0t
    Oct 10 '17 at 7:47










  • $begingroup$
    @t3chb0t chrs appreciate the feedback/comment.
    $endgroup$
    – BKSpurgeon
    Oct 10 '17 at 8:09






  • 1




    $begingroup$
    @t3chb0t There are issues with the code (e.g. variable naming, weird use of class-level fields, repetition of magic strings). But for the actual approach, an if-else chain or switch statement seem fine to me. If you try to treat every problem as a toy version of a guessed-at much more complex problem, all you'll end up teaching yourself is how to overengineer yourself into a corner.. because usually, when your problem does become more complex, it's not in exactly the way you anticipated. Going with a simple, good design now then iterating on it later is an important skill.
    $endgroup$
    – Ben Aaronson
    Oct 10 '17 at 17:59






  • 2




    $begingroup$
    @BenAaronson of course, but the simplest design would be using a dictionary for it. An if such as this one is an absolute no-go. Maybe if you write a toy-app this is acceptable but there is no place for such code in any production code. Personally, I can't stand if else ;-]
    $endgroup$
    – t3chb0t
    Oct 10 '17 at 18:03







  • 1




    $begingroup$
    While I'm personally not that strict to if-else constructions, this particular question is specifically asking for a more flexible solution, quote: I do not wish to hard coded it to compare the action. The strategy pattern is a way to go here.
    $endgroup$
    – Igor Soloydenko
    Oct 10 '17 at 19:28


















4












$begingroup$

Based on @Pouya Samie's answer a slightly different solution:



  • ActionManager encapsulates a dictionary that holds the actions.

  • Note that the dictionary's keys are not case sensitive.

  • You can even extend the action manager's functionality (Remove actions from outside, get list of all available actions, ...)

  • [x] OCP: Just add / remove list of actions without modifying the ActionManager

  • [x] SRP: ActionManager holds and manages the relation between action's name and its logic

_



public class ActionManager

private readonly Dictionary<string, Func<int, int, int>> myActions =
new Dictionary<string, Func<int, int, int>>(StringComparer.InvariantCultureIgnoreCase);

public void Add(string key, Func<int, int, int> action) => myActions.Add(key, action);

public int Calculat(string action, int value1, int value2)

Func<int, int, int> func;
if (!myActions.TryGetValue(action, out func))
throw new InvalidOperationException($"Action '0' does not exist.");
return func(value1, value2);




Usage:



public class MyClass

private readonly ActionManager myActionManager = new ActionManager();

public MyClass()

myActionManager.Add("Add", (a, b) => a + b);
myActionManager.Add("Subtract", (a, b) => a - b)
// ...


public int X get; set;
public int Y get; set;

private int Calculate(string action) => myActionManager.Calculat(action, X, Y);






share|improve this answer









$endgroup$




















    2












    $begingroup$

    I tend to avoid else if statements. If I’m just checking conditions and manipulating a value, then I’ll return in multiple if statements like this:



    private int Calculate(string sAction)

    int iTotal = 0;

    if(sAction == "Add")

    return X+Y;


    if(sAction == "Subtract")

    return X-Y;


    // No if statements entered.
    // Just return original value.

    return iTotal;



    But, looking at your arguments, I’d say it’s a good candidate for the Strategy pattern. In fact, the Wikipedia entry on the Strategy pattern covers this very scenario! You could have a factory that returns the correct strategy, and then call that:



    private int Calculate(string sAction)

    int iTotal = 0;

    CalculateActionFactory factory = new CalculateActionFactory;

    ICalculateAction action = factory.StrategyFor(sAction);

    return action.Execute(X, Y);


    public class CalculateActionFactory

    public ICalculateAction StrategyFor(string Action)

    switch (Action)

    case "Add":
    return new AddAction;

    case "Minus":
    return new MinusAction;


    throw new System.ArgumentException("Invalid action specified.");



    public interface ICalculateAction

    int Execute(int X, int Y);


    public class AddAction : ICalculateAction

    public int Execute(int X, int Y)

    return X+Y;



    public class MinusAction : ICalculateAction

    public int Execute(int X, int Y)

    return X-Y;




    Disclaimer: I’m not a C# developer, so apologies if the syntax is off!






    share|improve this answer









    $endgroup$












    • $begingroup$
      When using an abstraction for the actions, I would tend to add a "Name" property. Then you can replace the switch statement with something like:actions.FirstOrDefault(a => a.Name == name) ;)
      $endgroup$
      – JanDotNet
      Oct 10 '17 at 10:53






    • 2




      $begingroup$
      in my opinion, the formal strategy pattern as you wrote is just an old hack for the former lack of first order functions, and seems more or less obsolete now
      $endgroup$
      – Austin_Anderson
      Oct 10 '17 at 14:59










    • $begingroup$
      @Austin_Anderson: IMHO the strategy pattern is not obsolete: 1.) what if the strategy have more than one operation or other properties (e.g. additional description). 2.) If the algorithm is complex (e.g. consist of multiple functions and/or other object), then the concrete strategy class is a nice place to place that logic. Functional style may be succinct, but it does not always result in more readable and maintainable code. Therefore object oriented patterns should not necessarily be replaced by functional ones (IMO).
      $endgroup$
      – JanDotNet
      Oct 10 '17 at 16:11











    • $begingroup$
      @JanDotNet fair enough it still has it's place, but it's definitely overkill for this problem
      $endgroup$
      – Austin_Anderson
      Oct 10 '17 at 19:37


















    0












    $begingroup$

    What about this?



    public interface IAction

    int Calculate();

    string DisplayName get;



    You can implement as many as you need, bind to the combobox and unit test it pretty good.






    share|improve this answer









    $endgroup$













      Your Answer






      StackExchange.ifUsing("editor", function ()
      StackExchange.using("externalEditor", function ()
      StackExchange.using("snippets", function ()
      StackExchange.snippets.init();
      );
      );
      , "code-snippets");

      StackExchange.ready(function()
      var channelOptions =
      tags: "".split(" "),
      id: "196"
      ;
      initTagRenderer("".split(" "), "".split(" "), channelOptions);

      StackExchange.using("externalEditor", function()
      // Have to fire editor after snippets, if snippets enabled
      if (StackExchange.settings.snippets.snippetsEnabled)
      StackExchange.using("snippets", function()
      createEditor();
      );

      else
      createEditor();

      );

      function createEditor()
      StackExchange.prepareEditor(
      heartbeatType: 'answer',
      autoActivateHeartbeat: false,
      convertImagesToLinks: false,
      noModals: true,
      showLowRepImageUploadWarning: true,
      reputationToPostImages: null,
      bindNavPrevention: true,
      postfix: "",
      imageUploader:
      brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
      contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
      allowUrls: true
      ,
      onDemand: true,
      discardSelector: ".discard-answer"
      ,immediatelyShowMarkdownHelp:true
      );



      );













      draft saved

      draft discarded


















      StackExchange.ready(
      function ()
      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f177586%2fadd-or-subtract-two-numbers-depending-on-dropdown-selection%23new-answer', 'question_page');

      );

      Post as a guest















      Required, but never shown

























      5 Answers
      5






      active

      oldest

      votes








      5 Answers
      5






      active

      oldest

      votes









      active

      oldest

      votes






      active

      oldest

      votes









      9












      $begingroup$

      Be sure when you ever have a code that it has the chain of if else there should be an improvement. (even many programmers say you should not use if statement in your code as possible and some others say don't use else statement at all!)



      You can use something like this:



      First Add a class to manage your actions:



       public class ActionRegistry: Dictionary<string, Func<int, int, int>>

      public ActionRegistry()

      this.Add("Add", (x, y) => x + y);
      this.Add("Subtract", (x, y) => x - y);





      Then you can use that class like this:



      public class DoStuff

      private int Calculate(string sAction)

      var actionRegistry= new ActionRegistry();
      var a = 1;
      var b = 2;
      //var actionResult= actionRegistry[this should come from your drop down].Invoke(a, b);
      var actionResult= actionRegistry[sAction].Invoke(a, b);


      //you can even Register New Action Like this :
      actionRegistry.Add("Multiply",(x,y)=>x*y);

      //then you can use it somewhere else:
      var multiplyResult = actionRegistry["Multiply"].Invoke(a, b);
      return actionResult;




      Every time your action has changed you just need to add the new action in your ActionRegistry. With this approach, there is no need for that if-else statement.



      By the way, you can even use interface and DI to loosely couple the ActionManager.



      UPDATE Here my update using enums:



      First Declare an Enum :



      enum ActionType 

      Add,
      Subtract



      Then use that enum in your ActionRegistry class:



      public class ActionRegistry: Dictionary<int, Func<int, int, int>>

      public ActionRegistry()

      //it's better to register your actions outside the class
      // and don't use enum inside your class
      // but for simplicity i did that inside the class

      this.Add((int)ActionType.Add, (x, y) => x + y);
      this.Add((int)ActionType.Subtract, (x, y) => x - y);





      then you should change your calculate method like this :



       private int Calculate(int actionTypeCode)

      var actionRegistry= new ActionRegistry();
      var a = 1;
      var b = 2;
      //var actionResult= actionRegistry[this should come from your drop down].Invoke(a, b);
      var actionResult= actionRegistry[actionTypeCode].Invoke(a, b);

      return actionResult;



      Note that you should bind your dropdown list with your enum keys as value.
      I prefer to use an integer as my key because I can add more item later without changing my enum but it is not necessary.






      share|improve this answer











      $endgroup$








      • 3




        $begingroup$
        Simple and pragmatic solution :), You could also pass a string comparer to the dictionary's constructor to become a case insensitive dictionary: public ActionManager() : base(StringComparer.InvariantCultureIgnoreCase). How would you handle the case "action not available"?
        $endgroup$
        – JanDotNet
        Oct 10 '17 at 6:49






      • 1




        $begingroup$
        What about instead of using a String as an identifier, why not creating an Enum and then using it? This would put aside problems like aDD instead of Add or subtrat instead of Subtract.
        $endgroup$
        – auhmaan
        Oct 10 '17 at 9:12






      • 1




        $begingroup$
        One of the askers concerns was If I change the text in the drop down list, I need to change the function as well, and I don't see how that is addressed here. If the words in the text box change, this code still has to be revisited manually.
        $endgroup$
        – JPhi1618
        Oct 10 '17 at 14:17






      • 1




        $begingroup$
        This is a good, extensible approach. Just don't call it a Manager (nor Helper, nor Utils). It's an ActionRegistry, or ArithmeticOperations.
        $endgroup$
        – Igor Soloydenko
        Oct 10 '17 at 15:18






      • 1




        $begingroup$
        @JPhi1618 you should read the key and your dropdown list key from one place. you can use an enum or constant or database for that by the way your calculate method won't ever change.
        $endgroup$
        – Pouya Samie
        Oct 10 '17 at 18:18
















      9












      $begingroup$

      Be sure when you ever have a code that it has the chain of if else there should be an improvement. (even many programmers say you should not use if statement in your code as possible and some others say don't use else statement at all!)



      You can use something like this:



      First Add a class to manage your actions:



       public class ActionRegistry: Dictionary<string, Func<int, int, int>>

      public ActionRegistry()

      this.Add("Add", (x, y) => x + y);
      this.Add("Subtract", (x, y) => x - y);





      Then you can use that class like this:



      public class DoStuff

      private int Calculate(string sAction)

      var actionRegistry= new ActionRegistry();
      var a = 1;
      var b = 2;
      //var actionResult= actionRegistry[this should come from your drop down].Invoke(a, b);
      var actionResult= actionRegistry[sAction].Invoke(a, b);


      //you can even Register New Action Like this :
      actionRegistry.Add("Multiply",(x,y)=>x*y);

      //then you can use it somewhere else:
      var multiplyResult = actionRegistry["Multiply"].Invoke(a, b);
      return actionResult;




      Every time your action has changed you just need to add the new action in your ActionRegistry. With this approach, there is no need for that if-else statement.



      By the way, you can even use interface and DI to loosely couple the ActionManager.



      UPDATE Here my update using enums:



      First Declare an Enum :



      enum ActionType 

      Add,
      Subtract



      Then use that enum in your ActionRegistry class:



      public class ActionRegistry: Dictionary<int, Func<int, int, int>>

      public ActionRegistry()

      //it's better to register your actions outside the class
      // and don't use enum inside your class
      // but for simplicity i did that inside the class

      this.Add((int)ActionType.Add, (x, y) => x + y);
      this.Add((int)ActionType.Subtract, (x, y) => x - y);





      then you should change your calculate method like this :



       private int Calculate(int actionTypeCode)

      var actionRegistry= new ActionRegistry();
      var a = 1;
      var b = 2;
      //var actionResult= actionRegistry[this should come from your drop down].Invoke(a, b);
      var actionResult= actionRegistry[actionTypeCode].Invoke(a, b);

      return actionResult;



      Note that you should bind your dropdown list with your enum keys as value.
      I prefer to use an integer as my key because I can add more item later without changing my enum but it is not necessary.






      share|improve this answer











      $endgroup$








      • 3




        $begingroup$
        Simple and pragmatic solution :), You could also pass a string comparer to the dictionary's constructor to become a case insensitive dictionary: public ActionManager() : base(StringComparer.InvariantCultureIgnoreCase). How would you handle the case "action not available"?
        $endgroup$
        – JanDotNet
        Oct 10 '17 at 6:49






      • 1




        $begingroup$
        What about instead of using a String as an identifier, why not creating an Enum and then using it? This would put aside problems like aDD instead of Add or subtrat instead of Subtract.
        $endgroup$
        – auhmaan
        Oct 10 '17 at 9:12






      • 1




        $begingroup$
        One of the askers concerns was If I change the text in the drop down list, I need to change the function as well, and I don't see how that is addressed here. If the words in the text box change, this code still has to be revisited manually.
        $endgroup$
        – JPhi1618
        Oct 10 '17 at 14:17






      • 1




        $begingroup$
        This is a good, extensible approach. Just don't call it a Manager (nor Helper, nor Utils). It's an ActionRegistry, or ArithmeticOperations.
        $endgroup$
        – Igor Soloydenko
        Oct 10 '17 at 15:18






      • 1




        $begingroup$
        @JPhi1618 you should read the key and your dropdown list key from one place. you can use an enum or constant or database for that by the way your calculate method won't ever change.
        $endgroup$
        – Pouya Samie
        Oct 10 '17 at 18:18














      9












      9








      9





      $begingroup$

      Be sure when you ever have a code that it has the chain of if else there should be an improvement. (even many programmers say you should not use if statement in your code as possible and some others say don't use else statement at all!)



      You can use something like this:



      First Add a class to manage your actions:



       public class ActionRegistry: Dictionary<string, Func<int, int, int>>

      public ActionRegistry()

      this.Add("Add", (x, y) => x + y);
      this.Add("Subtract", (x, y) => x - y);





      Then you can use that class like this:



      public class DoStuff

      private int Calculate(string sAction)

      var actionRegistry= new ActionRegistry();
      var a = 1;
      var b = 2;
      //var actionResult= actionRegistry[this should come from your drop down].Invoke(a, b);
      var actionResult= actionRegistry[sAction].Invoke(a, b);


      //you can even Register New Action Like this :
      actionRegistry.Add("Multiply",(x,y)=>x*y);

      //then you can use it somewhere else:
      var multiplyResult = actionRegistry["Multiply"].Invoke(a, b);
      return actionResult;




      Every time your action has changed you just need to add the new action in your ActionRegistry. With this approach, there is no need for that if-else statement.



      By the way, you can even use interface and DI to loosely couple the ActionManager.



      UPDATE Here my update using enums:



      First Declare an Enum :



      enum ActionType 

      Add,
      Subtract



      Then use that enum in your ActionRegistry class:



      public class ActionRegistry: Dictionary<int, Func<int, int, int>>

      public ActionRegistry()

      //it's better to register your actions outside the class
      // and don't use enum inside your class
      // but for simplicity i did that inside the class

      this.Add((int)ActionType.Add, (x, y) => x + y);
      this.Add((int)ActionType.Subtract, (x, y) => x - y);





      then you should change your calculate method like this :



       private int Calculate(int actionTypeCode)

      var actionRegistry= new ActionRegistry();
      var a = 1;
      var b = 2;
      //var actionResult= actionRegistry[this should come from your drop down].Invoke(a, b);
      var actionResult= actionRegistry[actionTypeCode].Invoke(a, b);

      return actionResult;



      Note that you should bind your dropdown list with your enum keys as value.
      I prefer to use an integer as my key because I can add more item later without changing my enum but it is not necessary.






      share|improve this answer











      $endgroup$



      Be sure when you ever have a code that it has the chain of if else there should be an improvement. (even many programmers say you should not use if statement in your code as possible and some others say don't use else statement at all!)



      You can use something like this:



      First Add a class to manage your actions:



       public class ActionRegistry: Dictionary<string, Func<int, int, int>>

      public ActionRegistry()

      this.Add("Add", (x, y) => x + y);
      this.Add("Subtract", (x, y) => x - y);





      Then you can use that class like this:



      public class DoStuff

      private int Calculate(string sAction)

      var actionRegistry= new ActionRegistry();
      var a = 1;
      var b = 2;
      //var actionResult= actionRegistry[this should come from your drop down].Invoke(a, b);
      var actionResult= actionRegistry[sAction].Invoke(a, b);


      //you can even Register New Action Like this :
      actionRegistry.Add("Multiply",(x,y)=>x*y);

      //then you can use it somewhere else:
      var multiplyResult = actionRegistry["Multiply"].Invoke(a, b);
      return actionResult;




      Every time your action has changed you just need to add the new action in your ActionRegistry. With this approach, there is no need for that if-else statement.



      By the way, you can even use interface and DI to loosely couple the ActionManager.



      UPDATE Here my update using enums:



      First Declare an Enum :



      enum ActionType 

      Add,
      Subtract



      Then use that enum in your ActionRegistry class:



      public class ActionRegistry: Dictionary<int, Func<int, int, int>>

      public ActionRegistry()

      //it's better to register your actions outside the class
      // and don't use enum inside your class
      // but for simplicity i did that inside the class

      this.Add((int)ActionType.Add, (x, y) => x + y);
      this.Add((int)ActionType.Subtract, (x, y) => x - y);





      then you should change your calculate method like this :



       private int Calculate(int actionTypeCode)

      var actionRegistry= new ActionRegistry();
      var a = 1;
      var b = 2;
      //var actionResult= actionRegistry[this should come from your drop down].Invoke(a, b);
      var actionResult= actionRegistry[actionTypeCode].Invoke(a, b);

      return actionResult;



      Note that you should bind your dropdown list with your enum keys as value.
      I prefer to use an integer as my key because I can add more item later without changing my enum but it is not necessary.







      share|improve this answer














      share|improve this answer



      share|improve this answer








      edited Oct 10 '17 at 19:17

























      answered Oct 10 '17 at 6:38









      Pouya SamiePouya Samie

      22126




      22126







      • 3




        $begingroup$
        Simple and pragmatic solution :), You could also pass a string comparer to the dictionary's constructor to become a case insensitive dictionary: public ActionManager() : base(StringComparer.InvariantCultureIgnoreCase). How would you handle the case "action not available"?
        $endgroup$
        – JanDotNet
        Oct 10 '17 at 6:49






      • 1




        $begingroup$
        What about instead of using a String as an identifier, why not creating an Enum and then using it? This would put aside problems like aDD instead of Add or subtrat instead of Subtract.
        $endgroup$
        – auhmaan
        Oct 10 '17 at 9:12






      • 1




        $begingroup$
        One of the askers concerns was If I change the text in the drop down list, I need to change the function as well, and I don't see how that is addressed here. If the words in the text box change, this code still has to be revisited manually.
        $endgroup$
        – JPhi1618
        Oct 10 '17 at 14:17






      • 1




        $begingroup$
        This is a good, extensible approach. Just don't call it a Manager (nor Helper, nor Utils). It's an ActionRegistry, or ArithmeticOperations.
        $endgroup$
        – Igor Soloydenko
        Oct 10 '17 at 15:18






      • 1




        $begingroup$
        @JPhi1618 you should read the key and your dropdown list key from one place. you can use an enum or constant or database for that by the way your calculate method won't ever change.
        $endgroup$
        – Pouya Samie
        Oct 10 '17 at 18:18













      • 3




        $begingroup$
        Simple and pragmatic solution :), You could also pass a string comparer to the dictionary's constructor to become a case insensitive dictionary: public ActionManager() : base(StringComparer.InvariantCultureIgnoreCase). How would you handle the case "action not available"?
        $endgroup$
        – JanDotNet
        Oct 10 '17 at 6:49






      • 1




        $begingroup$
        What about instead of using a String as an identifier, why not creating an Enum and then using it? This would put aside problems like aDD instead of Add or subtrat instead of Subtract.
        $endgroup$
        – auhmaan
        Oct 10 '17 at 9:12






      • 1




        $begingroup$
        One of the askers concerns was If I change the text in the drop down list, I need to change the function as well, and I don't see how that is addressed here. If the words in the text box change, this code still has to be revisited manually.
        $endgroup$
        – JPhi1618
        Oct 10 '17 at 14:17






      • 1




        $begingroup$
        This is a good, extensible approach. Just don't call it a Manager (nor Helper, nor Utils). It's an ActionRegistry, or ArithmeticOperations.
        $endgroup$
        – Igor Soloydenko
        Oct 10 '17 at 15:18






      • 1




        $begingroup$
        @JPhi1618 you should read the key and your dropdown list key from one place. you can use an enum or constant or database for that by the way your calculate method won't ever change.
        $endgroup$
        – Pouya Samie
        Oct 10 '17 at 18:18








      3




      3




      $begingroup$
      Simple and pragmatic solution :), You could also pass a string comparer to the dictionary's constructor to become a case insensitive dictionary: public ActionManager() : base(StringComparer.InvariantCultureIgnoreCase). How would you handle the case "action not available"?
      $endgroup$
      – JanDotNet
      Oct 10 '17 at 6:49




      $begingroup$
      Simple and pragmatic solution :), You could also pass a string comparer to the dictionary's constructor to become a case insensitive dictionary: public ActionManager() : base(StringComparer.InvariantCultureIgnoreCase). How would you handle the case "action not available"?
      $endgroup$
      – JanDotNet
      Oct 10 '17 at 6:49




      1




      1




      $begingroup$
      What about instead of using a String as an identifier, why not creating an Enum and then using it? This would put aside problems like aDD instead of Add or subtrat instead of Subtract.
      $endgroup$
      – auhmaan
      Oct 10 '17 at 9:12




      $begingroup$
      What about instead of using a String as an identifier, why not creating an Enum and then using it? This would put aside problems like aDD instead of Add or subtrat instead of Subtract.
      $endgroup$
      – auhmaan
      Oct 10 '17 at 9:12




      1




      1




      $begingroup$
      One of the askers concerns was If I change the text in the drop down list, I need to change the function as well, and I don't see how that is addressed here. If the words in the text box change, this code still has to be revisited manually.
      $endgroup$
      – JPhi1618
      Oct 10 '17 at 14:17




      $begingroup$
      One of the askers concerns was If I change the text in the drop down list, I need to change the function as well, and I don't see how that is addressed here. If the words in the text box change, this code still has to be revisited manually.
      $endgroup$
      – JPhi1618
      Oct 10 '17 at 14:17




      1




      1




      $begingroup$
      This is a good, extensible approach. Just don't call it a Manager (nor Helper, nor Utils). It's an ActionRegistry, or ArithmeticOperations.
      $endgroup$
      – Igor Soloydenko
      Oct 10 '17 at 15:18




      $begingroup$
      This is a good, extensible approach. Just don't call it a Manager (nor Helper, nor Utils). It's an ActionRegistry, or ArithmeticOperations.
      $endgroup$
      – Igor Soloydenko
      Oct 10 '17 at 15:18




      1




      1




      $begingroup$
      @JPhi1618 you should read the key and your dropdown list key from one place. you can use an enum or constant or database for that by the way your calculate method won't ever change.
      $endgroup$
      – Pouya Samie
      Oct 10 '17 at 18:18





      $begingroup$
      @JPhi1618 you should read the key and your dropdown list key from one place. you can use an enum or constant or database for that by the way your calculate method won't ever change.
      $endgroup$
      – Pouya Samie
      Oct 10 '17 at 18:18














      7












      $begingroup$

      Is it worth changing? IMO: Code is best left as-is



      It is worth employing some form of polymorphism for one if statement? You gotta be kidding me: for one if statement - to abstract it out? That would make it more complicated, would it not? In my opinion - probably not. cf: @t3chb0t who has a different view.



      the code is small and very manageable. if it's already in place and working, and you have no reason to change it, then probably just leave it as is. there's nothing wrong with hard-coded code if it's working and will never change. but if changes start creeping in, then -- and only then consider refactoring. there's no point writing pure OOP for its own sake - perhaps that will make it harder to understand than it is now.



      Or if you did want to make it easier to change (slightly), then you could just use an enum. If you change the enum value from “Add” to “Addition” you can ask Visual Studio or Resharper to do all the work for you – but if you wanted to add a new item or decide to get rid of one, then certainly you will be making changes in two places and the open closed principle will be thus violated. Also note how the use of the temporary variables are somewhat more cleaned up below:



      internal class Program

      enum ListItem Add, Subtract

      private int Calculate(ListItem action)

      if (action == ListItem.Add)

      return 1234; // implement the calculation

      else if(action == ListItem.Subtract)

      return 1234; // implement the calculation

      else

      return 1234; // implement the calculation






      You could go for a polymorphic solution - as an academic exercise?



      You could implement the command design pattern and have a look at the MVVM design pattern (google them) - or other similar polymorphic solution. but you've already written the code!



      @PouyaSamie has written a very elegant solution (and it's beautiful in its sophistication) @MartinBeam has a nice answer too. In conclusion my question to you as you read some of the polymorphic solutions - (which are all great - and with the utmost respect to those folks): does it make it easier to understand the code or harder?






      share|improve this answer











      $endgroup$








      • 6




        $begingroup$
        The code is not best as-is, it's horrible. Everything is hardcoded. You should always bother or otherwise you never learn ;-]
        $endgroup$
        – t3chb0t
        Oct 10 '17 at 7:47










      • $begingroup$
        @t3chb0t chrs appreciate the feedback/comment.
        $endgroup$
        – BKSpurgeon
        Oct 10 '17 at 8:09






      • 1




        $begingroup$
        @t3chb0t There are issues with the code (e.g. variable naming, weird use of class-level fields, repetition of magic strings). But for the actual approach, an if-else chain or switch statement seem fine to me. If you try to treat every problem as a toy version of a guessed-at much more complex problem, all you'll end up teaching yourself is how to overengineer yourself into a corner.. because usually, when your problem does become more complex, it's not in exactly the way you anticipated. Going with a simple, good design now then iterating on it later is an important skill.
        $endgroup$
        – Ben Aaronson
        Oct 10 '17 at 17:59






      • 2




        $begingroup$
        @BenAaronson of course, but the simplest design would be using a dictionary for it. An if such as this one is an absolute no-go. Maybe if you write a toy-app this is acceptable but there is no place for such code in any production code. Personally, I can't stand if else ;-]
        $endgroup$
        – t3chb0t
        Oct 10 '17 at 18:03







      • 1




        $begingroup$
        While I'm personally not that strict to if-else constructions, this particular question is specifically asking for a more flexible solution, quote: I do not wish to hard coded it to compare the action. The strategy pattern is a way to go here.
        $endgroup$
        – Igor Soloydenko
        Oct 10 '17 at 19:28















      7












      $begingroup$

      Is it worth changing? IMO: Code is best left as-is



      It is worth employing some form of polymorphism for one if statement? You gotta be kidding me: for one if statement - to abstract it out? That would make it more complicated, would it not? In my opinion - probably not. cf: @t3chb0t who has a different view.



      the code is small and very manageable. if it's already in place and working, and you have no reason to change it, then probably just leave it as is. there's nothing wrong with hard-coded code if it's working and will never change. but if changes start creeping in, then -- and only then consider refactoring. there's no point writing pure OOP for its own sake - perhaps that will make it harder to understand than it is now.



      Or if you did want to make it easier to change (slightly), then you could just use an enum. If you change the enum value from “Add” to “Addition” you can ask Visual Studio or Resharper to do all the work for you – but if you wanted to add a new item or decide to get rid of one, then certainly you will be making changes in two places and the open closed principle will be thus violated. Also note how the use of the temporary variables are somewhat more cleaned up below:



      internal class Program

      enum ListItem Add, Subtract

      private int Calculate(ListItem action)

      if (action == ListItem.Add)

      return 1234; // implement the calculation

      else if(action == ListItem.Subtract)

      return 1234; // implement the calculation

      else

      return 1234; // implement the calculation






      You could go for a polymorphic solution - as an academic exercise?



      You could implement the command design pattern and have a look at the MVVM design pattern (google them) - or other similar polymorphic solution. but you've already written the code!



      @PouyaSamie has written a very elegant solution (and it's beautiful in its sophistication) @MartinBeam has a nice answer too. In conclusion my question to you as you read some of the polymorphic solutions - (which are all great - and with the utmost respect to those folks): does it make it easier to understand the code or harder?






      share|improve this answer











      $endgroup$








      • 6




        $begingroup$
        The code is not best as-is, it's horrible. Everything is hardcoded. You should always bother or otherwise you never learn ;-]
        $endgroup$
        – t3chb0t
        Oct 10 '17 at 7:47










      • $begingroup$
        @t3chb0t chrs appreciate the feedback/comment.
        $endgroup$
        – BKSpurgeon
        Oct 10 '17 at 8:09






      • 1




        $begingroup$
        @t3chb0t There are issues with the code (e.g. variable naming, weird use of class-level fields, repetition of magic strings). But for the actual approach, an if-else chain or switch statement seem fine to me. If you try to treat every problem as a toy version of a guessed-at much more complex problem, all you'll end up teaching yourself is how to overengineer yourself into a corner.. because usually, when your problem does become more complex, it's not in exactly the way you anticipated. Going with a simple, good design now then iterating on it later is an important skill.
        $endgroup$
        – Ben Aaronson
        Oct 10 '17 at 17:59






      • 2




        $begingroup$
        @BenAaronson of course, but the simplest design would be using a dictionary for it. An if such as this one is an absolute no-go. Maybe if you write a toy-app this is acceptable but there is no place for such code in any production code. Personally, I can't stand if else ;-]
        $endgroup$
        – t3chb0t
        Oct 10 '17 at 18:03







      • 1




        $begingroup$
        While I'm personally not that strict to if-else constructions, this particular question is specifically asking for a more flexible solution, quote: I do not wish to hard coded it to compare the action. The strategy pattern is a way to go here.
        $endgroup$
        – Igor Soloydenko
        Oct 10 '17 at 19:28













      7












      7








      7





      $begingroup$

      Is it worth changing? IMO: Code is best left as-is



      It is worth employing some form of polymorphism for one if statement? You gotta be kidding me: for one if statement - to abstract it out? That would make it more complicated, would it not? In my opinion - probably not. cf: @t3chb0t who has a different view.



      the code is small and very manageable. if it's already in place and working, and you have no reason to change it, then probably just leave it as is. there's nothing wrong with hard-coded code if it's working and will never change. but if changes start creeping in, then -- and only then consider refactoring. there's no point writing pure OOP for its own sake - perhaps that will make it harder to understand than it is now.



      Or if you did want to make it easier to change (slightly), then you could just use an enum. If you change the enum value from “Add” to “Addition” you can ask Visual Studio or Resharper to do all the work for you – but if you wanted to add a new item or decide to get rid of one, then certainly you will be making changes in two places and the open closed principle will be thus violated. Also note how the use of the temporary variables are somewhat more cleaned up below:



      internal class Program

      enum ListItem Add, Subtract

      private int Calculate(ListItem action)

      if (action == ListItem.Add)

      return 1234; // implement the calculation

      else if(action == ListItem.Subtract)

      return 1234; // implement the calculation

      else

      return 1234; // implement the calculation






      You could go for a polymorphic solution - as an academic exercise?



      You could implement the command design pattern and have a look at the MVVM design pattern (google them) - or other similar polymorphic solution. but you've already written the code!



      @PouyaSamie has written a very elegant solution (and it's beautiful in its sophistication) @MartinBeam has a nice answer too. In conclusion my question to you as you read some of the polymorphic solutions - (which are all great - and with the utmost respect to those folks): does it make it easier to understand the code or harder?






      share|improve this answer











      $endgroup$



      Is it worth changing? IMO: Code is best left as-is



      It is worth employing some form of polymorphism for one if statement? You gotta be kidding me: for one if statement - to abstract it out? That would make it more complicated, would it not? In my opinion - probably not. cf: @t3chb0t who has a different view.



      the code is small and very manageable. if it's already in place and working, and you have no reason to change it, then probably just leave it as is. there's nothing wrong with hard-coded code if it's working and will never change. but if changes start creeping in, then -- and only then consider refactoring. there's no point writing pure OOP for its own sake - perhaps that will make it harder to understand than it is now.



      Or if you did want to make it easier to change (slightly), then you could just use an enum. If you change the enum value from “Add” to “Addition” you can ask Visual Studio or Resharper to do all the work for you – but if you wanted to add a new item or decide to get rid of one, then certainly you will be making changes in two places and the open closed principle will be thus violated. Also note how the use of the temporary variables are somewhat more cleaned up below:



      internal class Program

      enum ListItem Add, Subtract

      private int Calculate(ListItem action)

      if (action == ListItem.Add)

      return 1234; // implement the calculation

      else if(action == ListItem.Subtract)

      return 1234; // implement the calculation

      else

      return 1234; // implement the calculation






      You could go for a polymorphic solution - as an academic exercise?



      You could implement the command design pattern and have a look at the MVVM design pattern (google them) - or other similar polymorphic solution. but you've already written the code!



      @PouyaSamie has written a very elegant solution (and it's beautiful in its sophistication) @MartinBeam has a nice answer too. In conclusion my question to you as you read some of the polymorphic solutions - (which are all great - and with the utmost respect to those folks): does it make it easier to understand the code or harder?







      share|improve this answer














      share|improve this answer



      share|improve this answer








      edited 10 mins ago

























      answered Oct 10 '17 at 6:14









      BKSpurgeonBKSpurgeon

      96129




      96129







      • 6




        $begingroup$
        The code is not best as-is, it's horrible. Everything is hardcoded. You should always bother or otherwise you never learn ;-]
        $endgroup$
        – t3chb0t
        Oct 10 '17 at 7:47










      • $begingroup$
        @t3chb0t chrs appreciate the feedback/comment.
        $endgroup$
        – BKSpurgeon
        Oct 10 '17 at 8:09






      • 1




        $begingroup$
        @t3chb0t There are issues with the code (e.g. variable naming, weird use of class-level fields, repetition of magic strings). But for the actual approach, an if-else chain or switch statement seem fine to me. If you try to treat every problem as a toy version of a guessed-at much more complex problem, all you'll end up teaching yourself is how to overengineer yourself into a corner.. because usually, when your problem does become more complex, it's not in exactly the way you anticipated. Going with a simple, good design now then iterating on it later is an important skill.
        $endgroup$
        – Ben Aaronson
        Oct 10 '17 at 17:59






      • 2




        $begingroup$
        @BenAaronson of course, but the simplest design would be using a dictionary for it. An if such as this one is an absolute no-go. Maybe if you write a toy-app this is acceptable but there is no place for such code in any production code. Personally, I can't stand if else ;-]
        $endgroup$
        – t3chb0t
        Oct 10 '17 at 18:03







      • 1




        $begingroup$
        While I'm personally not that strict to if-else constructions, this particular question is specifically asking for a more flexible solution, quote: I do not wish to hard coded it to compare the action. The strategy pattern is a way to go here.
        $endgroup$
        – Igor Soloydenko
        Oct 10 '17 at 19:28












      • 6




        $begingroup$
        The code is not best as-is, it's horrible. Everything is hardcoded. You should always bother or otherwise you never learn ;-]
        $endgroup$
        – t3chb0t
        Oct 10 '17 at 7:47










      • $begingroup$
        @t3chb0t chrs appreciate the feedback/comment.
        $endgroup$
        – BKSpurgeon
        Oct 10 '17 at 8:09






      • 1




        $begingroup$
        @t3chb0t There are issues with the code (e.g. variable naming, weird use of class-level fields, repetition of magic strings). But for the actual approach, an if-else chain or switch statement seem fine to me. If you try to treat every problem as a toy version of a guessed-at much more complex problem, all you'll end up teaching yourself is how to overengineer yourself into a corner.. because usually, when your problem does become more complex, it's not in exactly the way you anticipated. Going with a simple, good design now then iterating on it later is an important skill.
        $endgroup$
        – Ben Aaronson
        Oct 10 '17 at 17:59






      • 2




        $begingroup$
        @BenAaronson of course, but the simplest design would be using a dictionary for it. An if such as this one is an absolute no-go. Maybe if you write a toy-app this is acceptable but there is no place for such code in any production code. Personally, I can't stand if else ;-]
        $endgroup$
        – t3chb0t
        Oct 10 '17 at 18:03







      • 1




        $begingroup$
        While I'm personally not that strict to if-else constructions, this particular question is specifically asking for a more flexible solution, quote: I do not wish to hard coded it to compare the action. The strategy pattern is a way to go here.
        $endgroup$
        – Igor Soloydenko
        Oct 10 '17 at 19:28







      6




      6




      $begingroup$
      The code is not best as-is, it's horrible. Everything is hardcoded. You should always bother or otherwise you never learn ;-]
      $endgroup$
      – t3chb0t
      Oct 10 '17 at 7:47




      $begingroup$
      The code is not best as-is, it's horrible. Everything is hardcoded. You should always bother or otherwise you never learn ;-]
      $endgroup$
      – t3chb0t
      Oct 10 '17 at 7:47












      $begingroup$
      @t3chb0t chrs appreciate the feedback/comment.
      $endgroup$
      – BKSpurgeon
      Oct 10 '17 at 8:09




      $begingroup$
      @t3chb0t chrs appreciate the feedback/comment.
      $endgroup$
      – BKSpurgeon
      Oct 10 '17 at 8:09




      1




      1




      $begingroup$
      @t3chb0t There are issues with the code (e.g. variable naming, weird use of class-level fields, repetition of magic strings). But for the actual approach, an if-else chain or switch statement seem fine to me. If you try to treat every problem as a toy version of a guessed-at much more complex problem, all you'll end up teaching yourself is how to overengineer yourself into a corner.. because usually, when your problem does become more complex, it's not in exactly the way you anticipated. Going with a simple, good design now then iterating on it later is an important skill.
      $endgroup$
      – Ben Aaronson
      Oct 10 '17 at 17:59




      $begingroup$
      @t3chb0t There are issues with the code (e.g. variable naming, weird use of class-level fields, repetition of magic strings). But for the actual approach, an if-else chain or switch statement seem fine to me. If you try to treat every problem as a toy version of a guessed-at much more complex problem, all you'll end up teaching yourself is how to overengineer yourself into a corner.. because usually, when your problem does become more complex, it's not in exactly the way you anticipated. Going with a simple, good design now then iterating on it later is an important skill.
      $endgroup$
      – Ben Aaronson
      Oct 10 '17 at 17:59




      2




      2




      $begingroup$
      @BenAaronson of course, but the simplest design would be using a dictionary for it. An if such as this one is an absolute no-go. Maybe if you write a toy-app this is acceptable but there is no place for such code in any production code. Personally, I can't stand if else ;-]
      $endgroup$
      – t3chb0t
      Oct 10 '17 at 18:03





      $begingroup$
      @BenAaronson of course, but the simplest design would be using a dictionary for it. An if such as this one is an absolute no-go. Maybe if you write a toy-app this is acceptable but there is no place for such code in any production code. Personally, I can't stand if else ;-]
      $endgroup$
      – t3chb0t
      Oct 10 '17 at 18:03





      1




      1




      $begingroup$
      While I'm personally not that strict to if-else constructions, this particular question is specifically asking for a more flexible solution, quote: I do not wish to hard coded it to compare the action. The strategy pattern is a way to go here.
      $endgroup$
      – Igor Soloydenko
      Oct 10 '17 at 19:28




      $begingroup$
      While I'm personally not that strict to if-else constructions, this particular question is specifically asking for a more flexible solution, quote: I do not wish to hard coded it to compare the action. The strategy pattern is a way to go here.
      $endgroup$
      – Igor Soloydenko
      Oct 10 '17 at 19:28











      4












      $begingroup$

      Based on @Pouya Samie's answer a slightly different solution:



      • ActionManager encapsulates a dictionary that holds the actions.

      • Note that the dictionary's keys are not case sensitive.

      • You can even extend the action manager's functionality (Remove actions from outside, get list of all available actions, ...)

      • [x] OCP: Just add / remove list of actions without modifying the ActionManager

      • [x] SRP: ActionManager holds and manages the relation between action's name and its logic

      _



      public class ActionManager

      private readonly Dictionary<string, Func<int, int, int>> myActions =
      new Dictionary<string, Func<int, int, int>>(StringComparer.InvariantCultureIgnoreCase);

      public void Add(string key, Func<int, int, int> action) => myActions.Add(key, action);

      public int Calculat(string action, int value1, int value2)

      Func<int, int, int> func;
      if (!myActions.TryGetValue(action, out func))
      throw new InvalidOperationException($"Action '0' does not exist.");
      return func(value1, value2);




      Usage:



      public class MyClass

      private readonly ActionManager myActionManager = new ActionManager();

      public MyClass()

      myActionManager.Add("Add", (a, b) => a + b);
      myActionManager.Add("Subtract", (a, b) => a - b)
      // ...


      public int X get; set;
      public int Y get; set;

      private int Calculate(string action) => myActionManager.Calculat(action, X, Y);






      share|improve this answer









      $endgroup$

















        4












        $begingroup$

        Based on @Pouya Samie's answer a slightly different solution:



        • ActionManager encapsulates a dictionary that holds the actions.

        • Note that the dictionary's keys are not case sensitive.

        • You can even extend the action manager's functionality (Remove actions from outside, get list of all available actions, ...)

        • [x] OCP: Just add / remove list of actions without modifying the ActionManager

        • [x] SRP: ActionManager holds and manages the relation between action's name and its logic

        _



        public class ActionManager

        private readonly Dictionary<string, Func<int, int, int>> myActions =
        new Dictionary<string, Func<int, int, int>>(StringComparer.InvariantCultureIgnoreCase);

        public void Add(string key, Func<int, int, int> action) => myActions.Add(key, action);

        public int Calculat(string action, int value1, int value2)

        Func<int, int, int> func;
        if (!myActions.TryGetValue(action, out func))
        throw new InvalidOperationException($"Action '0' does not exist.");
        return func(value1, value2);




        Usage:



        public class MyClass

        private readonly ActionManager myActionManager = new ActionManager();

        public MyClass()

        myActionManager.Add("Add", (a, b) => a + b);
        myActionManager.Add("Subtract", (a, b) => a - b)
        // ...


        public int X get; set;
        public int Y get; set;

        private int Calculate(string action) => myActionManager.Calculat(action, X, Y);






        share|improve this answer









        $endgroup$















          4












          4








          4





          $begingroup$

          Based on @Pouya Samie's answer a slightly different solution:



          • ActionManager encapsulates a dictionary that holds the actions.

          • Note that the dictionary's keys are not case sensitive.

          • You can even extend the action manager's functionality (Remove actions from outside, get list of all available actions, ...)

          • [x] OCP: Just add / remove list of actions without modifying the ActionManager

          • [x] SRP: ActionManager holds and manages the relation between action's name and its logic

          _



          public class ActionManager

          private readonly Dictionary<string, Func<int, int, int>> myActions =
          new Dictionary<string, Func<int, int, int>>(StringComparer.InvariantCultureIgnoreCase);

          public void Add(string key, Func<int, int, int> action) => myActions.Add(key, action);

          public int Calculat(string action, int value1, int value2)

          Func<int, int, int> func;
          if (!myActions.TryGetValue(action, out func))
          throw new InvalidOperationException($"Action '0' does not exist.");
          return func(value1, value2);




          Usage:



          public class MyClass

          private readonly ActionManager myActionManager = new ActionManager();

          public MyClass()

          myActionManager.Add("Add", (a, b) => a + b);
          myActionManager.Add("Subtract", (a, b) => a - b)
          // ...


          public int X get; set;
          public int Y get; set;

          private int Calculate(string action) => myActionManager.Calculat(action, X, Y);






          share|improve this answer









          $endgroup$



          Based on @Pouya Samie's answer a slightly different solution:



          • ActionManager encapsulates a dictionary that holds the actions.

          • Note that the dictionary's keys are not case sensitive.

          • You can even extend the action manager's functionality (Remove actions from outside, get list of all available actions, ...)

          • [x] OCP: Just add / remove list of actions without modifying the ActionManager

          • [x] SRP: ActionManager holds and manages the relation between action's name and its logic

          _



          public class ActionManager

          private readonly Dictionary<string, Func<int, int, int>> myActions =
          new Dictionary<string, Func<int, int, int>>(StringComparer.InvariantCultureIgnoreCase);

          public void Add(string key, Func<int, int, int> action) => myActions.Add(key, action);

          public int Calculat(string action, int value1, int value2)

          Func<int, int, int> func;
          if (!myActions.TryGetValue(action, out func))
          throw new InvalidOperationException($"Action '0' does not exist.");
          return func(value1, value2);




          Usage:



          public class MyClass

          private readonly ActionManager myActionManager = new ActionManager();

          public MyClass()

          myActionManager.Add("Add", (a, b) => a + b);
          myActionManager.Add("Subtract", (a, b) => a - b)
          // ...


          public int X get; set;
          public int Y get; set;

          private int Calculate(string action) => myActionManager.Calculat(action, X, Y);







          share|improve this answer












          share|improve this answer



          share|improve this answer










          answered Oct 10 '17 at 8:28









          JanDotNetJanDotNet

          7,0131339




          7,0131339





















              2












              $begingroup$

              I tend to avoid else if statements. If I’m just checking conditions and manipulating a value, then I’ll return in multiple if statements like this:



              private int Calculate(string sAction)

              int iTotal = 0;

              if(sAction == "Add")

              return X+Y;


              if(sAction == "Subtract")

              return X-Y;


              // No if statements entered.
              // Just return original value.

              return iTotal;



              But, looking at your arguments, I’d say it’s a good candidate for the Strategy pattern. In fact, the Wikipedia entry on the Strategy pattern covers this very scenario! You could have a factory that returns the correct strategy, and then call that:



              private int Calculate(string sAction)

              int iTotal = 0;

              CalculateActionFactory factory = new CalculateActionFactory;

              ICalculateAction action = factory.StrategyFor(sAction);

              return action.Execute(X, Y);


              public class CalculateActionFactory

              public ICalculateAction StrategyFor(string Action)

              switch (Action)

              case "Add":
              return new AddAction;

              case "Minus":
              return new MinusAction;


              throw new System.ArgumentException("Invalid action specified.");



              public interface ICalculateAction

              int Execute(int X, int Y);


              public class AddAction : ICalculateAction

              public int Execute(int X, int Y)

              return X+Y;



              public class MinusAction : ICalculateAction

              public int Execute(int X, int Y)

              return X-Y;




              Disclaimer: I’m not a C# developer, so apologies if the syntax is off!






              share|improve this answer









              $endgroup$












              • $begingroup$
                When using an abstraction for the actions, I would tend to add a "Name" property. Then you can replace the switch statement with something like:actions.FirstOrDefault(a => a.Name == name) ;)
                $endgroup$
                – JanDotNet
                Oct 10 '17 at 10:53






              • 2




                $begingroup$
                in my opinion, the formal strategy pattern as you wrote is just an old hack for the former lack of first order functions, and seems more or less obsolete now
                $endgroup$
                – Austin_Anderson
                Oct 10 '17 at 14:59










              • $begingroup$
                @Austin_Anderson: IMHO the strategy pattern is not obsolete: 1.) what if the strategy have more than one operation or other properties (e.g. additional description). 2.) If the algorithm is complex (e.g. consist of multiple functions and/or other object), then the concrete strategy class is a nice place to place that logic. Functional style may be succinct, but it does not always result in more readable and maintainable code. Therefore object oriented patterns should not necessarily be replaced by functional ones (IMO).
                $endgroup$
                – JanDotNet
                Oct 10 '17 at 16:11











              • $begingroup$
                @JanDotNet fair enough it still has it's place, but it's definitely overkill for this problem
                $endgroup$
                – Austin_Anderson
                Oct 10 '17 at 19:37















              2












              $begingroup$

              I tend to avoid else if statements. If I’m just checking conditions and manipulating a value, then I’ll return in multiple if statements like this:



              private int Calculate(string sAction)

              int iTotal = 0;

              if(sAction == "Add")

              return X+Y;


              if(sAction == "Subtract")

              return X-Y;


              // No if statements entered.
              // Just return original value.

              return iTotal;



              But, looking at your arguments, I’d say it’s a good candidate for the Strategy pattern. In fact, the Wikipedia entry on the Strategy pattern covers this very scenario! You could have a factory that returns the correct strategy, and then call that:



              private int Calculate(string sAction)

              int iTotal = 0;

              CalculateActionFactory factory = new CalculateActionFactory;

              ICalculateAction action = factory.StrategyFor(sAction);

              return action.Execute(X, Y);


              public class CalculateActionFactory

              public ICalculateAction StrategyFor(string Action)

              switch (Action)

              case "Add":
              return new AddAction;

              case "Minus":
              return new MinusAction;


              throw new System.ArgumentException("Invalid action specified.");



              public interface ICalculateAction

              int Execute(int X, int Y);


              public class AddAction : ICalculateAction

              public int Execute(int X, int Y)

              return X+Y;



              public class MinusAction : ICalculateAction

              public int Execute(int X, int Y)

              return X-Y;




              Disclaimer: I’m not a C# developer, so apologies if the syntax is off!






              share|improve this answer









              $endgroup$












              • $begingroup$
                When using an abstraction for the actions, I would tend to add a "Name" property. Then you can replace the switch statement with something like:actions.FirstOrDefault(a => a.Name == name) ;)
                $endgroup$
                – JanDotNet
                Oct 10 '17 at 10:53






              • 2




                $begingroup$
                in my opinion, the formal strategy pattern as you wrote is just an old hack for the former lack of first order functions, and seems more or less obsolete now
                $endgroup$
                – Austin_Anderson
                Oct 10 '17 at 14:59










              • $begingroup$
                @Austin_Anderson: IMHO the strategy pattern is not obsolete: 1.) what if the strategy have more than one operation or other properties (e.g. additional description). 2.) If the algorithm is complex (e.g. consist of multiple functions and/or other object), then the concrete strategy class is a nice place to place that logic. Functional style may be succinct, but it does not always result in more readable and maintainable code. Therefore object oriented patterns should not necessarily be replaced by functional ones (IMO).
                $endgroup$
                – JanDotNet
                Oct 10 '17 at 16:11











              • $begingroup$
                @JanDotNet fair enough it still has it's place, but it's definitely overkill for this problem
                $endgroup$
                – Austin_Anderson
                Oct 10 '17 at 19:37













              2












              2








              2





              $begingroup$

              I tend to avoid else if statements. If I’m just checking conditions and manipulating a value, then I’ll return in multiple if statements like this:



              private int Calculate(string sAction)

              int iTotal = 0;

              if(sAction == "Add")

              return X+Y;


              if(sAction == "Subtract")

              return X-Y;


              // No if statements entered.
              // Just return original value.

              return iTotal;



              But, looking at your arguments, I’d say it’s a good candidate for the Strategy pattern. In fact, the Wikipedia entry on the Strategy pattern covers this very scenario! You could have a factory that returns the correct strategy, and then call that:



              private int Calculate(string sAction)

              int iTotal = 0;

              CalculateActionFactory factory = new CalculateActionFactory;

              ICalculateAction action = factory.StrategyFor(sAction);

              return action.Execute(X, Y);


              public class CalculateActionFactory

              public ICalculateAction StrategyFor(string Action)

              switch (Action)

              case "Add":
              return new AddAction;

              case "Minus":
              return new MinusAction;


              throw new System.ArgumentException("Invalid action specified.");



              public interface ICalculateAction

              int Execute(int X, int Y);


              public class AddAction : ICalculateAction

              public int Execute(int X, int Y)

              return X+Y;



              public class MinusAction : ICalculateAction

              public int Execute(int X, int Y)

              return X-Y;




              Disclaimer: I’m not a C# developer, so apologies if the syntax is off!






              share|improve this answer









              $endgroup$



              I tend to avoid else if statements. If I’m just checking conditions and manipulating a value, then I’ll return in multiple if statements like this:



              private int Calculate(string sAction)

              int iTotal = 0;

              if(sAction == "Add")

              return X+Y;


              if(sAction == "Subtract")

              return X-Y;


              // No if statements entered.
              // Just return original value.

              return iTotal;



              But, looking at your arguments, I’d say it’s a good candidate for the Strategy pattern. In fact, the Wikipedia entry on the Strategy pattern covers this very scenario! You could have a factory that returns the correct strategy, and then call that:



              private int Calculate(string sAction)

              int iTotal = 0;

              CalculateActionFactory factory = new CalculateActionFactory;

              ICalculateAction action = factory.StrategyFor(sAction);

              return action.Execute(X, Y);


              public class CalculateActionFactory

              public ICalculateAction StrategyFor(string Action)

              switch (Action)

              case "Add":
              return new AddAction;

              case "Minus":
              return new MinusAction;


              throw new System.ArgumentException("Invalid action specified.");



              public interface ICalculateAction

              int Execute(int X, int Y);


              public class AddAction : ICalculateAction

              public int Execute(int X, int Y)

              return X+Y;



              public class MinusAction : ICalculateAction

              public int Execute(int X, int Y)

              return X-Y;




              Disclaimer: I’m not a C# developer, so apologies if the syntax is off!







              share|improve this answer












              share|improve this answer



              share|improve this answer










              answered Oct 10 '17 at 10:22









              Martin BeanMartin Bean

              1879




              1879











              • $begingroup$
                When using an abstraction for the actions, I would tend to add a "Name" property. Then you can replace the switch statement with something like:actions.FirstOrDefault(a => a.Name == name) ;)
                $endgroup$
                – JanDotNet
                Oct 10 '17 at 10:53






              • 2




                $begingroup$
                in my opinion, the formal strategy pattern as you wrote is just an old hack for the former lack of first order functions, and seems more or less obsolete now
                $endgroup$
                – Austin_Anderson
                Oct 10 '17 at 14:59










              • $begingroup$
                @Austin_Anderson: IMHO the strategy pattern is not obsolete: 1.) what if the strategy have more than one operation or other properties (e.g. additional description). 2.) If the algorithm is complex (e.g. consist of multiple functions and/or other object), then the concrete strategy class is a nice place to place that logic. Functional style may be succinct, but it does not always result in more readable and maintainable code. Therefore object oriented patterns should not necessarily be replaced by functional ones (IMO).
                $endgroup$
                – JanDotNet
                Oct 10 '17 at 16:11











              • $begingroup$
                @JanDotNet fair enough it still has it's place, but it's definitely overkill for this problem
                $endgroup$
                – Austin_Anderson
                Oct 10 '17 at 19:37
















              • $begingroup$
                When using an abstraction for the actions, I would tend to add a "Name" property. Then you can replace the switch statement with something like:actions.FirstOrDefault(a => a.Name == name) ;)
                $endgroup$
                – JanDotNet
                Oct 10 '17 at 10:53






              • 2




                $begingroup$
                in my opinion, the formal strategy pattern as you wrote is just an old hack for the former lack of first order functions, and seems more or less obsolete now
                $endgroup$
                – Austin_Anderson
                Oct 10 '17 at 14:59










              • $begingroup$
                @Austin_Anderson: IMHO the strategy pattern is not obsolete: 1.) what if the strategy have more than one operation or other properties (e.g. additional description). 2.) If the algorithm is complex (e.g. consist of multiple functions and/or other object), then the concrete strategy class is a nice place to place that logic. Functional style may be succinct, but it does not always result in more readable and maintainable code. Therefore object oriented patterns should not necessarily be replaced by functional ones (IMO).
                $endgroup$
                – JanDotNet
                Oct 10 '17 at 16:11











              • $begingroup$
                @JanDotNet fair enough it still has it's place, but it's definitely overkill for this problem
                $endgroup$
                – Austin_Anderson
                Oct 10 '17 at 19:37















              $begingroup$
              When using an abstraction for the actions, I would tend to add a "Name" property. Then you can replace the switch statement with something like:actions.FirstOrDefault(a => a.Name == name) ;)
              $endgroup$
              – JanDotNet
              Oct 10 '17 at 10:53




              $begingroup$
              When using an abstraction for the actions, I would tend to add a "Name" property. Then you can replace the switch statement with something like:actions.FirstOrDefault(a => a.Name == name) ;)
              $endgroup$
              – JanDotNet
              Oct 10 '17 at 10:53




              2




              2




              $begingroup$
              in my opinion, the formal strategy pattern as you wrote is just an old hack for the former lack of first order functions, and seems more or less obsolete now
              $endgroup$
              – Austin_Anderson
              Oct 10 '17 at 14:59




              $begingroup$
              in my opinion, the formal strategy pattern as you wrote is just an old hack for the former lack of first order functions, and seems more or less obsolete now
              $endgroup$
              – Austin_Anderson
              Oct 10 '17 at 14:59












              $begingroup$
              @Austin_Anderson: IMHO the strategy pattern is not obsolete: 1.) what if the strategy have more than one operation or other properties (e.g. additional description). 2.) If the algorithm is complex (e.g. consist of multiple functions and/or other object), then the concrete strategy class is a nice place to place that logic. Functional style may be succinct, but it does not always result in more readable and maintainable code. Therefore object oriented patterns should not necessarily be replaced by functional ones (IMO).
              $endgroup$
              – JanDotNet
              Oct 10 '17 at 16:11





              $begingroup$
              @Austin_Anderson: IMHO the strategy pattern is not obsolete: 1.) what if the strategy have more than one operation or other properties (e.g. additional description). 2.) If the algorithm is complex (e.g. consist of multiple functions and/or other object), then the concrete strategy class is a nice place to place that logic. Functional style may be succinct, but it does not always result in more readable and maintainable code. Therefore object oriented patterns should not necessarily be replaced by functional ones (IMO).
              $endgroup$
              – JanDotNet
              Oct 10 '17 at 16:11













              $begingroup$
              @JanDotNet fair enough it still has it's place, but it's definitely overkill for this problem
              $endgroup$
              – Austin_Anderson
              Oct 10 '17 at 19:37




              $begingroup$
              @JanDotNet fair enough it still has it's place, but it's definitely overkill for this problem
              $endgroup$
              – Austin_Anderson
              Oct 10 '17 at 19:37











              0












              $begingroup$

              What about this?



              public interface IAction

              int Calculate();

              string DisplayName get;



              You can implement as many as you need, bind to the combobox and unit test it pretty good.






              share|improve this answer









              $endgroup$

















                0












                $begingroup$

                What about this?



                public interface IAction

                int Calculate();

                string DisplayName get;



                You can implement as many as you need, bind to the combobox and unit test it pretty good.






                share|improve this answer









                $endgroup$















                  0












                  0








                  0





                  $begingroup$

                  What about this?



                  public interface IAction

                  int Calculate();

                  string DisplayName get;



                  You can implement as many as you need, bind to the combobox and unit test it pretty good.






                  share|improve this answer









                  $endgroup$



                  What about this?



                  public interface IAction

                  int Calculate();

                  string DisplayName get;



                  You can implement as many as you need, bind to the combobox and unit test it pretty good.







                  share|improve this answer












                  share|improve this answer



                  share|improve this answer










                  answered Oct 10 '17 at 7:01









                  ogomrubogomrub

                  1464




                  1464



























                      draft saved

                      draft discarded
















































                      Thanks for contributing an answer to Code Review Stack Exchange!


                      • Please be sure to answer the question. Provide details and share your research!

                      But avoid


                      • Asking for help, clarification, or responding to other answers.

                      • Making statements based on opinion; back them up with references or personal experience.

                      Use MathJax to format equations. MathJax reference.


                      To learn more, see our tips on writing great answers.




                      draft saved


                      draft discarded














                      StackExchange.ready(
                      function ()
                      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f177586%2fadd-or-subtract-two-numbers-depending-on-dropdown-selection%23new-answer', 'question_page');

                      );

                      Post as a guest















                      Required, but never shown





















































                      Required, but never shown














                      Required, but never shown












                      Required, but never shown







                      Required, but never shown

































                      Required, but never shown














                      Required, but never shown












                      Required, but never shown







                      Required, but never shown







                      Popular posts from this blog

                      名間水力發電廠 目录 沿革 設施 鄰近設施 註釋 外部連結 导航菜单23°50′10″N 120°42′41″E / 23.83611°N 120.71139°E / 23.83611; 120.7113923°50′10″N 120°42′41″E / 23.83611°N 120.71139°E / 23.83611; 120.71139計畫概要原始内容臺灣第一座BOT 模式開發的水力發電廠-名間水力電廠名間水力發電廠 水利署首件BOT案原始内容《小檔案》名間電廠 首座BOT水力發電廠原始内容名間電廠BOT - 經濟部水利署中區水資源局

                      Prove that NP is closed under karp reduction?Space(n) not closed under Karp reductions - what about NTime(n)?Class P is closed under rotation?Prove or disprove that $NL$ is closed under polynomial many-one reductions$mathbfNC_2$ is closed under log-space reductionOn Karp reductionwhen can I know if a class (complexity) is closed under reduction (cook/karp)Check if class $PSPACE$ is closed under polyonomially space reductionIs NPSPACE also closed under polynomial-time reduction and under log-space reduction?Prove PSPACE is closed under complement?Prove PSPACE is closed under union?

                      Is my guitar’s action too high? Announcing the arrival of Valued Associate #679: Cesar Manara Planned maintenance scheduled April 23, 2019 at 23:30 UTC (7:30pm US/Eastern)Strings too stiff on a recently purchased acoustic guitar | Cort AD880CEIs the action of my guitar really high?Μy little finger is too weak to play guitarWith guitar, how long should I give my fingers to strengthen / callous?When playing a fret the guitar sounds mutedPlaying (Barre) chords up the guitar neckI think my guitar strings are wound too tight and I can't play barre chordsF barre chord on an SG guitarHow to find to the right strings of a barre chord by feel?High action on higher fret on my steel acoustic guitar