Four-function calculator with buttons for digits and operators












2














I would like make this calculator program more Object Oriented but I'm struggling with how to do it. The calculator works perfectly but I would like to have another class that does the calculations and then sends that information back to the main class to be displayed. Any tips? I'm not sure how to call the methods and return the calculations.



 public partial class MainWindow : Window
{
//Basic Variables
string input = string.Empty;
string op1 = string.Empty;
string op2 = string.Empty;
char operation;
double result = 0.0;

public MainWindow()
{
InitializeComponent();
}

private void btnOn_Click(object sender, RoutedEventArgs e)
{
displayTextbox.IsEnabled = true;
}

private void btnOff_Click(object sender, RoutedEventArgs e)
{
displayTextbox.IsEnabled = false;
displayTextbox.Text = String.Empty;
displayTextbox.Text = "Off";
}

private void btn0_Click(object sender, RoutedEventArgs e)
{
this.displayTextbox.Text = "";
input += 0;
this.displayTextbox.Text += input;
}

private void btn1_Click(object sender, RoutedEventArgs e)
{
this.displayTextbox.Text = "";
input += 1;
this.displayTextbox.Text += input;
}

private void btn2_Click(object sender, RoutedEventArgs e)
{
this.displayTextbox.Text = "";
input += 2;
this.displayTextbox.Text += input;
}

private void btn3_Click(object sender, RoutedEventArgs e)
{
this.displayTextbox.Text = "";
input += 3;
this.displayTextbox.Text += input;
}

private void btn4_Click(object sender, RoutedEventArgs e)
{
this.displayTextbox.Text = "";
input += 4;
this.displayTextbox.Text += input;
}

private void btn5_Click(object sender, RoutedEventArgs e)
{
this.displayTextbox.Text = "";
input += 5;
this.displayTextbox.Text += input;
}

private void btn6_Click(object sender, RoutedEventArgs e)
{
this.displayTextbox.Text = "";
input += 6;
this.displayTextbox.Text += input;
}

private void btn7_Click(object sender, RoutedEventArgs e)
{
this.displayTextbox.Text = "";
input += 7;
this.displayTextbox.Text += input;
}

private void btn8_Click(object sender, RoutedEventArgs e)
{
this.displayTextbox.Text = "";
input += 8;
this.displayTextbox.Text += input;
}

private void btn9_Click(object sender, RoutedEventArgs e)
{
this.displayTextbox.Text = "";
input += 9;
this.displayTextbox.Text += input;
}

private void btnClear_Click(object sender, RoutedEventArgs e)
{
displayTextbox.Text = "";
this.input = string.Empty;
this.op1 = string.Empty;
this.op2 = string.Empty;
}

private void btnAdd_Click(object sender, RoutedEventArgs e)
{
op1 = input;
operation = '+';
input = string.Empty;
}

private void btnDivision_Click(object sender, RoutedEventArgs e)
{
op1 = input;
operation = '/';
input = string.Empty;
}

private void btnMultiple_Click(object sender, RoutedEventArgs e)
{
op1 = input;
operation = '*';
input = string.Empty;
}

private void btnSubtract_Click(object sender, RoutedEventArgs e)
{
op1 = input;
operation = '-';
input = string.Empty;
}

private void btnEquals_Click(object sender, RoutedEventArgs e)
{
op2 = input;
double num1, num2;
double.TryParse(op1, out num1);
double.TryParse(op2, out num2);

if (operation == '+')
{
result = num1 + num2;
displayTextbox.Text = result.ToString();
}
else if (operation == '-')
{
result = num1 - num2;
displayTextbox.Text = result.ToString();
}
else if (operation == '*')
{
result = num1 * num2;
displayTextbox.Text = result.ToString();
}
else if (operation == '/')
{
result = num1 / num2;
displayTextbox.Text = result.ToString();
}
}
}









share|improve this question
























  • Odd to me that input is string.
    – paparazzo
    Nov 13 '18 at 19:45
















2














I would like make this calculator program more Object Oriented but I'm struggling with how to do it. The calculator works perfectly but I would like to have another class that does the calculations and then sends that information back to the main class to be displayed. Any tips? I'm not sure how to call the methods and return the calculations.



 public partial class MainWindow : Window
{
//Basic Variables
string input = string.Empty;
string op1 = string.Empty;
string op2 = string.Empty;
char operation;
double result = 0.0;

public MainWindow()
{
InitializeComponent();
}

private void btnOn_Click(object sender, RoutedEventArgs e)
{
displayTextbox.IsEnabled = true;
}

private void btnOff_Click(object sender, RoutedEventArgs e)
{
displayTextbox.IsEnabled = false;
displayTextbox.Text = String.Empty;
displayTextbox.Text = "Off";
}

private void btn0_Click(object sender, RoutedEventArgs e)
{
this.displayTextbox.Text = "";
input += 0;
this.displayTextbox.Text += input;
}

private void btn1_Click(object sender, RoutedEventArgs e)
{
this.displayTextbox.Text = "";
input += 1;
this.displayTextbox.Text += input;
}

private void btn2_Click(object sender, RoutedEventArgs e)
{
this.displayTextbox.Text = "";
input += 2;
this.displayTextbox.Text += input;
}

private void btn3_Click(object sender, RoutedEventArgs e)
{
this.displayTextbox.Text = "";
input += 3;
this.displayTextbox.Text += input;
}

private void btn4_Click(object sender, RoutedEventArgs e)
{
this.displayTextbox.Text = "";
input += 4;
this.displayTextbox.Text += input;
}

private void btn5_Click(object sender, RoutedEventArgs e)
{
this.displayTextbox.Text = "";
input += 5;
this.displayTextbox.Text += input;
}

private void btn6_Click(object sender, RoutedEventArgs e)
{
this.displayTextbox.Text = "";
input += 6;
this.displayTextbox.Text += input;
}

private void btn7_Click(object sender, RoutedEventArgs e)
{
this.displayTextbox.Text = "";
input += 7;
this.displayTextbox.Text += input;
}

private void btn8_Click(object sender, RoutedEventArgs e)
{
this.displayTextbox.Text = "";
input += 8;
this.displayTextbox.Text += input;
}

private void btn9_Click(object sender, RoutedEventArgs e)
{
this.displayTextbox.Text = "";
input += 9;
this.displayTextbox.Text += input;
}

private void btnClear_Click(object sender, RoutedEventArgs e)
{
displayTextbox.Text = "";
this.input = string.Empty;
this.op1 = string.Empty;
this.op2 = string.Empty;
}

private void btnAdd_Click(object sender, RoutedEventArgs e)
{
op1 = input;
operation = '+';
input = string.Empty;
}

private void btnDivision_Click(object sender, RoutedEventArgs e)
{
op1 = input;
operation = '/';
input = string.Empty;
}

private void btnMultiple_Click(object sender, RoutedEventArgs e)
{
op1 = input;
operation = '*';
input = string.Empty;
}

private void btnSubtract_Click(object sender, RoutedEventArgs e)
{
op1 = input;
operation = '-';
input = string.Empty;
}

private void btnEquals_Click(object sender, RoutedEventArgs e)
{
op2 = input;
double num1, num2;
double.TryParse(op1, out num1);
double.TryParse(op2, out num2);

if (operation == '+')
{
result = num1 + num2;
displayTextbox.Text = result.ToString();
}
else if (operation == '-')
{
result = num1 - num2;
displayTextbox.Text = result.ToString();
}
else if (operation == '*')
{
result = num1 * num2;
displayTextbox.Text = result.ToString();
}
else if (operation == '/')
{
result = num1 / num2;
displayTextbox.Text = result.ToString();
}
}
}









share|improve this question
























  • Odd to me that input is string.
    – paparazzo
    Nov 13 '18 at 19:45














2












2








2







I would like make this calculator program more Object Oriented but I'm struggling with how to do it. The calculator works perfectly but I would like to have another class that does the calculations and then sends that information back to the main class to be displayed. Any tips? I'm not sure how to call the methods and return the calculations.



 public partial class MainWindow : Window
{
//Basic Variables
string input = string.Empty;
string op1 = string.Empty;
string op2 = string.Empty;
char operation;
double result = 0.0;

public MainWindow()
{
InitializeComponent();
}

private void btnOn_Click(object sender, RoutedEventArgs e)
{
displayTextbox.IsEnabled = true;
}

private void btnOff_Click(object sender, RoutedEventArgs e)
{
displayTextbox.IsEnabled = false;
displayTextbox.Text = String.Empty;
displayTextbox.Text = "Off";
}

private void btn0_Click(object sender, RoutedEventArgs e)
{
this.displayTextbox.Text = "";
input += 0;
this.displayTextbox.Text += input;
}

private void btn1_Click(object sender, RoutedEventArgs e)
{
this.displayTextbox.Text = "";
input += 1;
this.displayTextbox.Text += input;
}

private void btn2_Click(object sender, RoutedEventArgs e)
{
this.displayTextbox.Text = "";
input += 2;
this.displayTextbox.Text += input;
}

private void btn3_Click(object sender, RoutedEventArgs e)
{
this.displayTextbox.Text = "";
input += 3;
this.displayTextbox.Text += input;
}

private void btn4_Click(object sender, RoutedEventArgs e)
{
this.displayTextbox.Text = "";
input += 4;
this.displayTextbox.Text += input;
}

private void btn5_Click(object sender, RoutedEventArgs e)
{
this.displayTextbox.Text = "";
input += 5;
this.displayTextbox.Text += input;
}

private void btn6_Click(object sender, RoutedEventArgs e)
{
this.displayTextbox.Text = "";
input += 6;
this.displayTextbox.Text += input;
}

private void btn7_Click(object sender, RoutedEventArgs e)
{
this.displayTextbox.Text = "";
input += 7;
this.displayTextbox.Text += input;
}

private void btn8_Click(object sender, RoutedEventArgs e)
{
this.displayTextbox.Text = "";
input += 8;
this.displayTextbox.Text += input;
}

private void btn9_Click(object sender, RoutedEventArgs e)
{
this.displayTextbox.Text = "";
input += 9;
this.displayTextbox.Text += input;
}

private void btnClear_Click(object sender, RoutedEventArgs e)
{
displayTextbox.Text = "";
this.input = string.Empty;
this.op1 = string.Empty;
this.op2 = string.Empty;
}

private void btnAdd_Click(object sender, RoutedEventArgs e)
{
op1 = input;
operation = '+';
input = string.Empty;
}

private void btnDivision_Click(object sender, RoutedEventArgs e)
{
op1 = input;
operation = '/';
input = string.Empty;
}

private void btnMultiple_Click(object sender, RoutedEventArgs e)
{
op1 = input;
operation = '*';
input = string.Empty;
}

private void btnSubtract_Click(object sender, RoutedEventArgs e)
{
op1 = input;
operation = '-';
input = string.Empty;
}

private void btnEquals_Click(object sender, RoutedEventArgs e)
{
op2 = input;
double num1, num2;
double.TryParse(op1, out num1);
double.TryParse(op2, out num2);

if (operation == '+')
{
result = num1 + num2;
displayTextbox.Text = result.ToString();
}
else if (operation == '-')
{
result = num1 - num2;
displayTextbox.Text = result.ToString();
}
else if (operation == '*')
{
result = num1 * num2;
displayTextbox.Text = result.ToString();
}
else if (operation == '/')
{
result = num1 / num2;
displayTextbox.Text = result.ToString();
}
}
}









share|improve this question















I would like make this calculator program more Object Oriented but I'm struggling with how to do it. The calculator works perfectly but I would like to have another class that does the calculations and then sends that information back to the main class to be displayed. Any tips? I'm not sure how to call the methods and return the calculations.



 public partial class MainWindow : Window
{
//Basic Variables
string input = string.Empty;
string op1 = string.Empty;
string op2 = string.Empty;
char operation;
double result = 0.0;

public MainWindow()
{
InitializeComponent();
}

private void btnOn_Click(object sender, RoutedEventArgs e)
{
displayTextbox.IsEnabled = true;
}

private void btnOff_Click(object sender, RoutedEventArgs e)
{
displayTextbox.IsEnabled = false;
displayTextbox.Text = String.Empty;
displayTextbox.Text = "Off";
}

private void btn0_Click(object sender, RoutedEventArgs e)
{
this.displayTextbox.Text = "";
input += 0;
this.displayTextbox.Text += input;
}

private void btn1_Click(object sender, RoutedEventArgs e)
{
this.displayTextbox.Text = "";
input += 1;
this.displayTextbox.Text += input;
}

private void btn2_Click(object sender, RoutedEventArgs e)
{
this.displayTextbox.Text = "";
input += 2;
this.displayTextbox.Text += input;
}

private void btn3_Click(object sender, RoutedEventArgs e)
{
this.displayTextbox.Text = "";
input += 3;
this.displayTextbox.Text += input;
}

private void btn4_Click(object sender, RoutedEventArgs e)
{
this.displayTextbox.Text = "";
input += 4;
this.displayTextbox.Text += input;
}

private void btn5_Click(object sender, RoutedEventArgs e)
{
this.displayTextbox.Text = "";
input += 5;
this.displayTextbox.Text += input;
}

private void btn6_Click(object sender, RoutedEventArgs e)
{
this.displayTextbox.Text = "";
input += 6;
this.displayTextbox.Text += input;
}

private void btn7_Click(object sender, RoutedEventArgs e)
{
this.displayTextbox.Text = "";
input += 7;
this.displayTextbox.Text += input;
}

private void btn8_Click(object sender, RoutedEventArgs e)
{
this.displayTextbox.Text = "";
input += 8;
this.displayTextbox.Text += input;
}

private void btn9_Click(object sender, RoutedEventArgs e)
{
this.displayTextbox.Text = "";
input += 9;
this.displayTextbox.Text += input;
}

private void btnClear_Click(object sender, RoutedEventArgs e)
{
displayTextbox.Text = "";
this.input = string.Empty;
this.op1 = string.Empty;
this.op2 = string.Empty;
}

private void btnAdd_Click(object sender, RoutedEventArgs e)
{
op1 = input;
operation = '+';
input = string.Empty;
}

private void btnDivision_Click(object sender, RoutedEventArgs e)
{
op1 = input;
operation = '/';
input = string.Empty;
}

private void btnMultiple_Click(object sender, RoutedEventArgs e)
{
op1 = input;
operation = '*';
input = string.Empty;
}

private void btnSubtract_Click(object sender, RoutedEventArgs e)
{
op1 = input;
operation = '-';
input = string.Empty;
}

private void btnEquals_Click(object sender, RoutedEventArgs e)
{
op2 = input;
double num1, num2;
double.TryParse(op1, out num1);
double.TryParse(op2, out num2);

if (operation == '+')
{
result = num1 + num2;
displayTextbox.Text = result.ToString();
}
else if (operation == '-')
{
result = num1 - num2;
displayTextbox.Text = result.ToString();
}
else if (operation == '*')
{
result = num1 * num2;
displayTextbox.Text = result.ToString();
}
else if (operation == '/')
{
result = num1 / num2;
displayTextbox.Text = result.ToString();
}
}
}






c# object-oriented calculator gui






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 13 '18 at 4:25









200_success

128k15152413




128k15152413










asked Nov 12 '18 at 23:02









Jeff Ryan

132




132












  • Odd to me that input is string.
    – paparazzo
    Nov 13 '18 at 19:45


















  • Odd to me that input is string.
    – paparazzo
    Nov 13 '18 at 19:45
















Odd to me that input is string.
– paparazzo
Nov 13 '18 at 19:45




Odd to me that input is string.
– paparazzo
Nov 13 '18 at 19:45










2 Answers
2






active

oldest

votes


















2














Some tips from me:



1) You should separate the UI logic from your main logic. In your case, the logic is the calculation, so you should make a class for it. Don't think about the UI, just code your logic. It must be completely independent of the UI. This way you could test your calculation logic without creating windows every time and you could use another UI instead of the current one. You could even use the console.



2) Your class shouldn't inherit from Window. Instead, give an instance of Window to your class. One reason for this is, that it will pollute your MainWindows interface with many methods which you probably won't need. In general, favor Composition over inheritance.



3) You could define operation as a lambda:



// instead of:
operation = '-';
// use this:
operation = (a, b) => a - b;


It would make your btnEquals_Click method shorter and easier by removing the if-checks:



    private void btnEquals_Click(object sender, RoutedEventArgs e)
{
op2 = input;
double num1, num2;
double.TryParse(op1, out num1);
double.TryParse(op2, out num2);
displayTextbox.Text = (operation(num1, num2).toString(); // don't check, just apply
}


4) You are repeating yourself multiple times:



this.displayTextbox.Text = "";
input += <some num>;
this.displayTextbox.Text += input;


Introduce a method that takes the number and does all this. It would reduce the amount of lines of code and generally: It's bad to have duplications because if it's wrong, you'll have to fix multiple places. See DRY.



5) I don't know what the initialize method does (used in the constructor), but I would advise you to stay away from this habit. A constructor should be lightweight and easy because as a user I don't want to get problems when I create your objects. I can understand that something might go wrong if I call a method because that's action and it can fail. But the creation of objects should be smooth and easy.






share|improve this answer

















  • 4




    Regarding 5) thats how Visual Studio does it. Visual Studio creates partial classes for a Form where the Form settings (how the controls are aligned etc) are placed in a file e.g Form1.Designer.cs and the code the user type inside Form1.cs.
    – Heslacher
    Nov 13 '18 at 5:57



















2














    private void btn0_Click(object sender, RoutedEventArgs e)
{
this.displayTextbox.Text = "";
input += 0;
this.displayTextbox.Text += input;
}

private void btn1_Click(object sender, RoutedEventArgs e)
{
this.displayTextbox.Text = "";
input += 1;
this.displayTextbox.Text += input;
}

//And 8 more...


It's very obvious that these methods are copy/paste and then you effectively change a single value.



A good rule of thumb is that a developer should count like a caveman: "one, two, many". When something is used more than twice, you need to abstract it into a reusable algorithm.



Doing so is, at first glance, very simple:



    private void numberButton_Click(object sender, RoutedEventArgs e)
{
this.displayTextbox.Text = "";
input += 0;
this.displayTextbox.Text += input;
}


And then you set all your number buttons to have this same click event handler.



However, there is one issue: you need to know the input value of each button. This can be done in several ways. I'll list two: the quick and dirty way and the better way.



Quick and dirty

Since your button label equals the number you wish to add, you can effectively use that to get the right value. This isn't a great solution (it ties your UI to your logic), but it is the simplest solution I can think of:



    private void numberButton_Click(object sender, RoutedEventArgs e)
{
this.displayTextbox.Text = "";
input += Convert.ToInt32((sender as Button)?.Text ?? "0");
this.displayTextbox.Text += input;
}


But this isn't the best solution. It feels (and demonstrably is) dirty.



Better

A better way would be to create a NumberButton class which works exactly like a button, but also contains a number value that you can use.



Create a new WPF user control. Change the XAML to use a <Button> tag instead of a <UserControl> tag, and set the code behind class to inherit from button:



public partial class NumberButton : Button {}


And then you add your additional value property:



public int NumberValue { get; set; }


In your calculator window XAML, you can now set this property:



<NumberButton ... NumberValue="1" Click="numberButton_Click" />


And then you can retrieve the NumberValue in the click event:



    private void numberButton_Click(object sender, RoutedEventArgs e)
{
this.displayTextbox.Text = "";
input += (sender as NumberButton)?.NumberValue ?? 0;
this.displayTextbox.Text += input;
}


In case you were using WinForms instead of WPF, here's an MSDN guide on how to inherit from existing controls.






share|improve this answer





















    Your Answer





    StackExchange.ifUsing("editor", function () {
    return StackExchange.using("mathjaxEditing", function () {
    StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix) {
    StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
    });
    });
    }, "mathjax-editing");

    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%2f207516%2ffour-function-calculator-with-buttons-for-digits-and-operators%23new-answer', 'question_page');
    }
    );

    Post as a guest















    Required, but never shown

























    2 Answers
    2






    active

    oldest

    votes








    2 Answers
    2






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    2














    Some tips from me:



    1) You should separate the UI logic from your main logic. In your case, the logic is the calculation, so you should make a class for it. Don't think about the UI, just code your logic. It must be completely independent of the UI. This way you could test your calculation logic without creating windows every time and you could use another UI instead of the current one. You could even use the console.



    2) Your class shouldn't inherit from Window. Instead, give an instance of Window to your class. One reason for this is, that it will pollute your MainWindows interface with many methods which you probably won't need. In general, favor Composition over inheritance.



    3) You could define operation as a lambda:



    // instead of:
    operation = '-';
    // use this:
    operation = (a, b) => a - b;


    It would make your btnEquals_Click method shorter and easier by removing the if-checks:



        private void btnEquals_Click(object sender, RoutedEventArgs e)
    {
    op2 = input;
    double num1, num2;
    double.TryParse(op1, out num1);
    double.TryParse(op2, out num2);
    displayTextbox.Text = (operation(num1, num2).toString(); // don't check, just apply
    }


    4) You are repeating yourself multiple times:



    this.displayTextbox.Text = "";
    input += <some num>;
    this.displayTextbox.Text += input;


    Introduce a method that takes the number and does all this. It would reduce the amount of lines of code and generally: It's bad to have duplications because if it's wrong, you'll have to fix multiple places. See DRY.



    5) I don't know what the initialize method does (used in the constructor), but I would advise you to stay away from this habit. A constructor should be lightweight and easy because as a user I don't want to get problems when I create your objects. I can understand that something might go wrong if I call a method because that's action and it can fail. But the creation of objects should be smooth and easy.






    share|improve this answer

















    • 4




      Regarding 5) thats how Visual Studio does it. Visual Studio creates partial classes for a Form where the Form settings (how the controls are aligned etc) are placed in a file e.g Form1.Designer.cs and the code the user type inside Form1.cs.
      – Heslacher
      Nov 13 '18 at 5:57
















    2














    Some tips from me:



    1) You should separate the UI logic from your main logic. In your case, the logic is the calculation, so you should make a class for it. Don't think about the UI, just code your logic. It must be completely independent of the UI. This way you could test your calculation logic without creating windows every time and you could use another UI instead of the current one. You could even use the console.



    2) Your class shouldn't inherit from Window. Instead, give an instance of Window to your class. One reason for this is, that it will pollute your MainWindows interface with many methods which you probably won't need. In general, favor Composition over inheritance.



    3) You could define operation as a lambda:



    // instead of:
    operation = '-';
    // use this:
    operation = (a, b) => a - b;


    It would make your btnEquals_Click method shorter and easier by removing the if-checks:



        private void btnEquals_Click(object sender, RoutedEventArgs e)
    {
    op2 = input;
    double num1, num2;
    double.TryParse(op1, out num1);
    double.TryParse(op2, out num2);
    displayTextbox.Text = (operation(num1, num2).toString(); // don't check, just apply
    }


    4) You are repeating yourself multiple times:



    this.displayTextbox.Text = "";
    input += <some num>;
    this.displayTextbox.Text += input;


    Introduce a method that takes the number and does all this. It would reduce the amount of lines of code and generally: It's bad to have duplications because if it's wrong, you'll have to fix multiple places. See DRY.



    5) I don't know what the initialize method does (used in the constructor), but I would advise you to stay away from this habit. A constructor should be lightweight and easy because as a user I don't want to get problems when I create your objects. I can understand that something might go wrong if I call a method because that's action and it can fail. But the creation of objects should be smooth and easy.






    share|improve this answer

















    • 4




      Regarding 5) thats how Visual Studio does it. Visual Studio creates partial classes for a Form where the Form settings (how the controls are aligned etc) are placed in a file e.g Form1.Designer.cs and the code the user type inside Form1.cs.
      – Heslacher
      Nov 13 '18 at 5:57














    2












    2








    2






    Some tips from me:



    1) You should separate the UI logic from your main logic. In your case, the logic is the calculation, so you should make a class for it. Don't think about the UI, just code your logic. It must be completely independent of the UI. This way you could test your calculation logic without creating windows every time and you could use another UI instead of the current one. You could even use the console.



    2) Your class shouldn't inherit from Window. Instead, give an instance of Window to your class. One reason for this is, that it will pollute your MainWindows interface with many methods which you probably won't need. In general, favor Composition over inheritance.



    3) You could define operation as a lambda:



    // instead of:
    operation = '-';
    // use this:
    operation = (a, b) => a - b;


    It would make your btnEquals_Click method shorter and easier by removing the if-checks:



        private void btnEquals_Click(object sender, RoutedEventArgs e)
    {
    op2 = input;
    double num1, num2;
    double.TryParse(op1, out num1);
    double.TryParse(op2, out num2);
    displayTextbox.Text = (operation(num1, num2).toString(); // don't check, just apply
    }


    4) You are repeating yourself multiple times:



    this.displayTextbox.Text = "";
    input += <some num>;
    this.displayTextbox.Text += input;


    Introduce a method that takes the number and does all this. It would reduce the amount of lines of code and generally: It's bad to have duplications because if it's wrong, you'll have to fix multiple places. See DRY.



    5) I don't know what the initialize method does (used in the constructor), but I would advise you to stay away from this habit. A constructor should be lightweight and easy because as a user I don't want to get problems when I create your objects. I can understand that something might go wrong if I call a method because that's action and it can fail. But the creation of objects should be smooth and easy.






    share|improve this answer












    Some tips from me:



    1) You should separate the UI logic from your main logic. In your case, the logic is the calculation, so you should make a class for it. Don't think about the UI, just code your logic. It must be completely independent of the UI. This way you could test your calculation logic without creating windows every time and you could use another UI instead of the current one. You could even use the console.



    2) Your class shouldn't inherit from Window. Instead, give an instance of Window to your class. One reason for this is, that it will pollute your MainWindows interface with many methods which you probably won't need. In general, favor Composition over inheritance.



    3) You could define operation as a lambda:



    // instead of:
    operation = '-';
    // use this:
    operation = (a, b) => a - b;


    It would make your btnEquals_Click method shorter and easier by removing the if-checks:



        private void btnEquals_Click(object sender, RoutedEventArgs e)
    {
    op2 = input;
    double num1, num2;
    double.TryParse(op1, out num1);
    double.TryParse(op2, out num2);
    displayTextbox.Text = (operation(num1, num2).toString(); // don't check, just apply
    }


    4) You are repeating yourself multiple times:



    this.displayTextbox.Text = "";
    input += <some num>;
    this.displayTextbox.Text += input;


    Introduce a method that takes the number and does all this. It would reduce the amount of lines of code and generally: It's bad to have duplications because if it's wrong, you'll have to fix multiple places. See DRY.



    5) I don't know what the initialize method does (used in the constructor), but I would advise you to stay away from this habit. A constructor should be lightweight and easy because as a user I don't want to get problems when I create your objects. I can understand that something might go wrong if I call a method because that's action and it can fail. But the creation of objects should be smooth and easy.







    share|improve this answer












    share|improve this answer



    share|improve this answer










    answered Nov 13 '18 at 0:12









    Synth

    1495




    1495








    • 4




      Regarding 5) thats how Visual Studio does it. Visual Studio creates partial classes for a Form where the Form settings (how the controls are aligned etc) are placed in a file e.g Form1.Designer.cs and the code the user type inside Form1.cs.
      – Heslacher
      Nov 13 '18 at 5:57














    • 4




      Regarding 5) thats how Visual Studio does it. Visual Studio creates partial classes for a Form where the Form settings (how the controls are aligned etc) are placed in a file e.g Form1.Designer.cs and the code the user type inside Form1.cs.
      – Heslacher
      Nov 13 '18 at 5:57








    4




    4




    Regarding 5) thats how Visual Studio does it. Visual Studio creates partial classes for a Form where the Form settings (how the controls are aligned etc) are placed in a file e.g Form1.Designer.cs and the code the user type inside Form1.cs.
    – Heslacher
    Nov 13 '18 at 5:57




    Regarding 5) thats how Visual Studio does it. Visual Studio creates partial classes for a Form where the Form settings (how the controls are aligned etc) are placed in a file e.g Form1.Designer.cs and the code the user type inside Form1.cs.
    – Heslacher
    Nov 13 '18 at 5:57













    2














        private void btn0_Click(object sender, RoutedEventArgs e)
    {
    this.displayTextbox.Text = "";
    input += 0;
    this.displayTextbox.Text += input;
    }

    private void btn1_Click(object sender, RoutedEventArgs e)
    {
    this.displayTextbox.Text = "";
    input += 1;
    this.displayTextbox.Text += input;
    }

    //And 8 more...


    It's very obvious that these methods are copy/paste and then you effectively change a single value.



    A good rule of thumb is that a developer should count like a caveman: "one, two, many". When something is used more than twice, you need to abstract it into a reusable algorithm.



    Doing so is, at first glance, very simple:



        private void numberButton_Click(object sender, RoutedEventArgs e)
    {
    this.displayTextbox.Text = "";
    input += 0;
    this.displayTextbox.Text += input;
    }


    And then you set all your number buttons to have this same click event handler.



    However, there is one issue: you need to know the input value of each button. This can be done in several ways. I'll list two: the quick and dirty way and the better way.



    Quick and dirty

    Since your button label equals the number you wish to add, you can effectively use that to get the right value. This isn't a great solution (it ties your UI to your logic), but it is the simplest solution I can think of:



        private void numberButton_Click(object sender, RoutedEventArgs e)
    {
    this.displayTextbox.Text = "";
    input += Convert.ToInt32((sender as Button)?.Text ?? "0");
    this.displayTextbox.Text += input;
    }


    But this isn't the best solution. It feels (and demonstrably is) dirty.



    Better

    A better way would be to create a NumberButton class which works exactly like a button, but also contains a number value that you can use.



    Create a new WPF user control. Change the XAML to use a <Button> tag instead of a <UserControl> tag, and set the code behind class to inherit from button:



    public partial class NumberButton : Button {}


    And then you add your additional value property:



    public int NumberValue { get; set; }


    In your calculator window XAML, you can now set this property:



    <NumberButton ... NumberValue="1" Click="numberButton_Click" />


    And then you can retrieve the NumberValue in the click event:



        private void numberButton_Click(object sender, RoutedEventArgs e)
    {
    this.displayTextbox.Text = "";
    input += (sender as NumberButton)?.NumberValue ?? 0;
    this.displayTextbox.Text += input;
    }


    In case you were using WinForms instead of WPF, here's an MSDN guide on how to inherit from existing controls.






    share|improve this answer


























      2














          private void btn0_Click(object sender, RoutedEventArgs e)
      {
      this.displayTextbox.Text = "";
      input += 0;
      this.displayTextbox.Text += input;
      }

      private void btn1_Click(object sender, RoutedEventArgs e)
      {
      this.displayTextbox.Text = "";
      input += 1;
      this.displayTextbox.Text += input;
      }

      //And 8 more...


      It's very obvious that these methods are copy/paste and then you effectively change a single value.



      A good rule of thumb is that a developer should count like a caveman: "one, two, many". When something is used more than twice, you need to abstract it into a reusable algorithm.



      Doing so is, at first glance, very simple:



          private void numberButton_Click(object sender, RoutedEventArgs e)
      {
      this.displayTextbox.Text = "";
      input += 0;
      this.displayTextbox.Text += input;
      }


      And then you set all your number buttons to have this same click event handler.



      However, there is one issue: you need to know the input value of each button. This can be done in several ways. I'll list two: the quick and dirty way and the better way.



      Quick and dirty

      Since your button label equals the number you wish to add, you can effectively use that to get the right value. This isn't a great solution (it ties your UI to your logic), but it is the simplest solution I can think of:



          private void numberButton_Click(object sender, RoutedEventArgs e)
      {
      this.displayTextbox.Text = "";
      input += Convert.ToInt32((sender as Button)?.Text ?? "0");
      this.displayTextbox.Text += input;
      }


      But this isn't the best solution. It feels (and demonstrably is) dirty.



      Better

      A better way would be to create a NumberButton class which works exactly like a button, but also contains a number value that you can use.



      Create a new WPF user control. Change the XAML to use a <Button> tag instead of a <UserControl> tag, and set the code behind class to inherit from button:



      public partial class NumberButton : Button {}


      And then you add your additional value property:



      public int NumberValue { get; set; }


      In your calculator window XAML, you can now set this property:



      <NumberButton ... NumberValue="1" Click="numberButton_Click" />


      And then you can retrieve the NumberValue in the click event:



          private void numberButton_Click(object sender, RoutedEventArgs e)
      {
      this.displayTextbox.Text = "";
      input += (sender as NumberButton)?.NumberValue ?? 0;
      this.displayTextbox.Text += input;
      }


      In case you were using WinForms instead of WPF, here's an MSDN guide on how to inherit from existing controls.






      share|improve this answer
























        2












        2








        2






            private void btn0_Click(object sender, RoutedEventArgs e)
        {
        this.displayTextbox.Text = "";
        input += 0;
        this.displayTextbox.Text += input;
        }

        private void btn1_Click(object sender, RoutedEventArgs e)
        {
        this.displayTextbox.Text = "";
        input += 1;
        this.displayTextbox.Text += input;
        }

        //And 8 more...


        It's very obvious that these methods are copy/paste and then you effectively change a single value.



        A good rule of thumb is that a developer should count like a caveman: "one, two, many". When something is used more than twice, you need to abstract it into a reusable algorithm.



        Doing so is, at first glance, very simple:



            private void numberButton_Click(object sender, RoutedEventArgs e)
        {
        this.displayTextbox.Text = "";
        input += 0;
        this.displayTextbox.Text += input;
        }


        And then you set all your number buttons to have this same click event handler.



        However, there is one issue: you need to know the input value of each button. This can be done in several ways. I'll list two: the quick and dirty way and the better way.



        Quick and dirty

        Since your button label equals the number you wish to add, you can effectively use that to get the right value. This isn't a great solution (it ties your UI to your logic), but it is the simplest solution I can think of:



            private void numberButton_Click(object sender, RoutedEventArgs e)
        {
        this.displayTextbox.Text = "";
        input += Convert.ToInt32((sender as Button)?.Text ?? "0");
        this.displayTextbox.Text += input;
        }


        But this isn't the best solution. It feels (and demonstrably is) dirty.



        Better

        A better way would be to create a NumberButton class which works exactly like a button, but also contains a number value that you can use.



        Create a new WPF user control. Change the XAML to use a <Button> tag instead of a <UserControl> tag, and set the code behind class to inherit from button:



        public partial class NumberButton : Button {}


        And then you add your additional value property:



        public int NumberValue { get; set; }


        In your calculator window XAML, you can now set this property:



        <NumberButton ... NumberValue="1" Click="numberButton_Click" />


        And then you can retrieve the NumberValue in the click event:



            private void numberButton_Click(object sender, RoutedEventArgs e)
        {
        this.displayTextbox.Text = "";
        input += (sender as NumberButton)?.NumberValue ?? 0;
        this.displayTextbox.Text += input;
        }


        In case you were using WinForms instead of WPF, here's an MSDN guide on how to inherit from existing controls.






        share|improve this answer












            private void btn0_Click(object sender, RoutedEventArgs e)
        {
        this.displayTextbox.Text = "";
        input += 0;
        this.displayTextbox.Text += input;
        }

        private void btn1_Click(object sender, RoutedEventArgs e)
        {
        this.displayTextbox.Text = "";
        input += 1;
        this.displayTextbox.Text += input;
        }

        //And 8 more...


        It's very obvious that these methods are copy/paste and then you effectively change a single value.



        A good rule of thumb is that a developer should count like a caveman: "one, two, many". When something is used more than twice, you need to abstract it into a reusable algorithm.



        Doing so is, at first glance, very simple:



            private void numberButton_Click(object sender, RoutedEventArgs e)
        {
        this.displayTextbox.Text = "";
        input += 0;
        this.displayTextbox.Text += input;
        }


        And then you set all your number buttons to have this same click event handler.



        However, there is one issue: you need to know the input value of each button. This can be done in several ways. I'll list two: the quick and dirty way and the better way.



        Quick and dirty

        Since your button label equals the number you wish to add, you can effectively use that to get the right value. This isn't a great solution (it ties your UI to your logic), but it is the simplest solution I can think of:



            private void numberButton_Click(object sender, RoutedEventArgs e)
        {
        this.displayTextbox.Text = "";
        input += Convert.ToInt32((sender as Button)?.Text ?? "0");
        this.displayTextbox.Text += input;
        }


        But this isn't the best solution. It feels (and demonstrably is) dirty.



        Better

        A better way would be to create a NumberButton class which works exactly like a button, but also contains a number value that you can use.



        Create a new WPF user control. Change the XAML to use a <Button> tag instead of a <UserControl> tag, and set the code behind class to inherit from button:



        public partial class NumberButton : Button {}


        And then you add your additional value property:



        public int NumberValue { get; set; }


        In your calculator window XAML, you can now set this property:



        <NumberButton ... NumberValue="1" Click="numberButton_Click" />


        And then you can retrieve the NumberValue in the click event:



            private void numberButton_Click(object sender, RoutedEventArgs e)
        {
        this.displayTextbox.Text = "";
        input += (sender as NumberButton)?.NumberValue ?? 0;
        this.displayTextbox.Text += input;
        }


        In case you were using WinForms instead of WPF, here's an MSDN guide on how to inherit from existing controls.







        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered Nov 13 '18 at 8:25









        Flater

        3,092920




        3,092920






























            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.





            Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


            Please pay close attention to the following guidance:


            • 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.


            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%2f207516%2ffour-function-calculator-with-buttons-for-digits-and-operators%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

            How to make a Squid Proxy server?

            第一次世界大戦

            Touch on Surface Book