How to fill an array from several textboxes? - c#

I am trying to fill an array from several textboxes, then calculate with the values in the array.
I have the following code, but don't know why it doesn't work. Explained in the code:
private void button1_Click(object sender, EventArgs e)
{
double[] temperaturen = new double[6];
temperaturen[0] = double.Parse(textBox1.Text);
MessageBox.Show(temperaturen[0].ToString()); //the messagebox is just to test if
//it works
}
The above code works, but it stops working after I add more values from more textboxes:
private void button1_Click(object sender, EventArgs e)
{
double[] temperaturen = new double[6];
temperaturen[0] = double.Parse(textBox1.Text); //now it stops working and gives
temperaturen[1] = double.Parse(textBox2.Text); //the following error:
temperaturen[2] = double.Parse(textBox3.Text); //format exceptions was unhandled.
temperaturen[3] = double.Parse(textBox4.Text);
temperaturen[4] = double.Parse(textBox5.Text);
temperaturen[5] = double.Parse(textBox6.Text);
temperaturen[6] = double.Parse(textBox7.Text);
MessageBox.Show(temperaturen[0].ToString());
}
Does anybody know if parsing from textbox is the right way of doing this whatsoever? and why this does not work?

Please note, that you have 7 textboxes, not 6, so you should declare new double[7].
To avoid such errors, let's query with a help of Linq:
using System.Linq;
...
double[] temperaturen = new TextBox[] {
textBox1, textBox2, textBox3,
textBox4, textBox5, textBox6,
textBox7 }
.Select(box => double.TryParse(box.Text, out var value) ? value : double.NaN)
.ToArray();
Note, that text box can have text which is not a valid floating point value (say, "bla-bla-bla"),
I put double.NaN (Not a Number) in this case.

What actually solved the problem is:
Adding a try catch, and changing the array to have 7 values.
The final code, fully functioning.
private void button1_Click(object sender, EventArgs e)
{
decimal[] temperaturen = new decimal[7];//the array
try // try block
{
temperaturen[0] = decimal.Parse(txtZondag.Text);//parsing input
temperaturen[1] = decimal.Parse(txtMaandag.Text);//from
temperaturen[2] = decimal.Parse(txtDinsdag.Text);//textboxes
temperaturen[3] = decimal.Parse(txtWoensdag.Text);
temperaturen[4] = decimal.Parse(txtDonderdag.Text);
temperaturen[5] = decimal.Parse(txtVrijdag.Text);
temperaturen[6] = decimal.Parse(txtZaterdag.Text);
decimal temp = 10.2m;//decimal temp for calculations
decimal uitkomst1 = 0.0m;//decimal for sum.
uitkomst1 = temperaturen[0] - temp;//calculation
textBox8.Text = uitkomst1.ToString();
decimal uitkomst2 = 0;
uitkomst2 = temperaturen[1] - temp;
textBox9.Text = uitkomst2.ToString();
decimal uitkomst3 = 0;
uitkomst3 = temperaturen[2] - temp;
textBox10.Text = uitkomst3.ToString();
decimal uitkomst4 = 0.0m;
uitkomst4 = temperaturen[3] = temp;
textBox11.Text = uitkomst4.ToString();
decimal uitkomst5 = 0;
uitkomst5 = temperaturen[4] - temp;
textBox12.Text = uitkomst5.ToString();
decimal uitkomst6 = 0;
uitkomst6 = temperaturen[5] - temp;
textBox13.Text = uitkomst6.ToString();
decimal uitkomst7 = 0;
uitkomst7 = temperaturen[6] - temp;
textBox14.Text = uitkomst7.ToString();
}
catch (Exception exception)//catch block
{
MessageBox.Show("Incorrecte invoer! " + exception.Message);
}
}

Your code is not SOLID, meaning that it doesn't follow the guidelines of the Solid principle. If you are not familiar with SOLID, consider to read some background information about SOLID
For instance, your code has more than one Responsibility. This principle states that each class should have a single purpose or responsibility. This helps reduce bugs by:
Simplifying the code,
Making testing easier, and
Allowing for more modularity (i.e., the ability to reuse and combine code).
In your case: you need a class that can read the temperature from somewhere. This can be from a text box, or from the internet, a digital thermometer, anything:
interface IThermometer
{
double ReadTemperature();
}
class TextBoxThermometer : IThermometer
{
public TextBox TextBox {get; set;}
public double ReadTemperature()
{
// TODO: add some error checking: null textbox, no proper value in the textbox, etc.
return Double.Parse(this.TextBox.Text);
}
}
This class is easy to create, easy to test, and easy to maintain: if you want a decimal as temperature, the changes will be minimal.
Once you've got this class, and created unit tests for them, you can be certain that the class is working correctly, for any TextBox that you attach to this class.
Apparently you don't have one Thermometer, you've got a collection of Thermometers. From each Thermometer you can read the temperature:
class ThermometerCollection : IReadOnlyCollection<IThermometer>
{
public List<IThermometer> Thermometers {get; set;}
// TODO: implement IReadOnlyCollection<IThermometer>
public double ReadTemperatur(int thermometerIndex)
{
// TODO: check validity of thermometerIndex
return this.Thermometers[thermometerIndex].ReadTemperature();
}
}
The thermometer collection is also a fairly simple class with functions with only one or two lines. Easy to understand, Easy to test, easy to maintain. If desired you can even have different types of thermometers in the collection: one that reads from a text box, another that reads from the internet.
Because you've unit tested the class, you can be certain that it works with all kinds of IThermometers.
Inside your form:
private IReadOnlyCollection<IThermometer> Thermometers {get;}
public MyForm() // constructor
{
InitializeComponent();
this.Thermometers = new ThermometerCollection
{
Thermometers = new List<IThermometer>()
{
new TextBoxThermometer() {TextBox = this.TextBox1},
new TextBoxThermometer() {TextBox = this.TextBox2},
new TextBoxThermometer() {TextBox = this.TextBox3},
new TextBoxThermometer() {TextBox = this.TextBox4},
new TextBoxThermometer() {TextBox = this.TextBox5},
new TextBoxThermometer() {TextBox = this.TextBox6},
},
}
}
Now your form has one ThermometerCollection with six thermometers. For users of these thermometers, it is not important how they get their temperature. They might read them from a text box, but if in future you decide to read the temperature from the internet, changes in your form will be minimal. Remember: because you've got unit tests for your TextBoxThermometer you can be sure that this type of Thermometer works flawless.
Now that you've decoupled the Thermometer from where it gets the temperature, in your form you can write methods to read the temperature
public double ReadTemperature(int thermometerIndex)
{
return this.ThermometerCollection.ReadTemperature(thermometerIndex);
}
Again a one liner method. Note that this is a method in your Form, so it is fairly difficult to unit test. But since you have tested the ThermometerCollection thoroughly, you hardly miss the test.
private void button1_Click(object sender, EventArgs e)
{
this.ProcessTemperatures();
// TODO: do other things that must be done when button1 is clicked
}
public void ProcessTemperatures()
{
// Read the temperatures, and process them:
ICollection<double> measuredTemperatures = Enumerable.Range(1,6)
.Select(thermometerIndex => this.ReadTemperature(thermometerIndex)
.ToList();
this.ProcessTemperatures(measuredTemperatures);
}
public void ProcessTemperatures(ICollection<double> measuredTemperatures)
{
// TODO: do what you wanted to do with your measured temperatures
}
I've decoupled the button click from the processing. If later you decide that you want to do something different if the button is clicked, changes will be minimal. Also, if you want to add a menu item that will also process the temperatures: the procedure will be a one liner.
Summary
Because I made methods that only have one specific task, you have methods that are easy to understand, easy to unit test, simple to change and maintain, simple to reuse.
Because I separated your from from the notion of Thermometers, you can reuse the thermometers in a different form. You have unit tested the Thermometer classes, so you can be certain that it will also work if you want 10 Thermometers.
Because I separated the Thermometer from where it gets its data from, it is easy to use a different type of Thermometer, for instance one that reads from a cell in a table, or from the internet. Users of your Thermometer class won't notice the difference.

Related

String is in wrong format c# [duplicate]

This question already has answers here:
Input string was not in a correct format in double.Parse
(5 answers)
Closed 4 years ago.
I'm trying to figure out why when I run my program and press the submit button I get an error saying that my list is in the wrong format. A little background on the program: It's for my visual programming class. The program is for a bank account. I tried to comment on what each section is to make it kinda easier to read
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
//Tab 1 Create and close account
private void Submitbtn_Click(object sender, EventArgs e)
{
double x;
if (OpenRdo.Checked == true && Nametxtbx.TextLength > 0)
{
double.TryParse(Nametxtbx.Text, out x);
// after clicking the button there is
// no number; it says system.random
Random acct = new Random();
int AccountNumber = acct.Next(5, 1000);
outputlbl.Text = acct.ToString();
}
// list for accounts
// This is where it says I have the error
// that my list is in the wrong format
var accounts = new List<Account>
{
new Account(Nametxtbx.Text, double.Parse(outputlbl.Text), 0)
};
// Write these records to a file
WriteFile(accounts);
// message box when you create account
if (ValidateChildren(ValidationConstraints.Enabled))
{
MessageBox.Show("Account Created", "Message",
MessageBoxButtons.OK, MessageBoxIcon.Information);
}
}
//writing to the file
static void WriteFile(List<Account> accts)
{
StreamWriter outputFile = File.CreateText("accounts.txt");
string record;
foreach (var acct in accts)
{
record = $"{acct.Name},{acct.Balance}";
Console.WriteLine($"Writing record: {record}");
outputFile.WriteLine(record);
}
outputFile.Close();
}
}
As far as I can tell (this is rather a lot of code), the issues are those lines:
Random acct = new Random();
int AccountNumber = acct.Next(5, 1000);
outputlbl.Text = acct.ToString();
You set the label to "System.Random" (because you call ToString() on the wrong thing). And that can not be sensibly casted into a integer later.
Ideally you should not even retrieve the data from the UI. If you got a integer in code behind, keep it there. Use it. But with the seperation between Events that might not be always possible.
I would recommend, do not just parse a text if you not know whats in the textbox.
Rather do something like this
if(double.TryParse (outputlbl.Text, out double outputNumber))
{
new Account(Nametxtbx.Text, outputNumber, 0);
}
Also, have a look at the formatprovider

Creating Calculator with Class - C#, However unable to solve error

I'm trying to create a Calculator with a Class. However using references from the internet particularly from this website (https://www.sourcecodester.com/tutorials/c/7548/simple-calculator-using-class-c.html)
It did not mention to declare "Information" or whatsoever.
When I typed in the code, the error list return with Information does not exist in current context.
Is there a way to modify the code below? Thank you so much.
public partial class Form4 : Form
{
public Form4()
{
InitializeComponent();
}
private void Form4_Load(object sender, EventArgs e)
{
}
public void RadioButton_Click(object sender, System.EventArgs e)
{
//call a constructor method and return to cal as an instance of a class
calculate cal = new calculate();
//declaring the string variable represent as a textbox
string txtnum1 = TextBox1.Text;
string txtnum2 = TextBox2.Text;
//declaring the double variable
double dbl_val1 = default(double);
double dbl_val2 = default(double);
if (**Information**.IsNumeric(txtnum1) && **Information**.IsNumeric(txtnum2)) //check if the textbox has a numeric value
{
//convert the string to double
dbl_val1 = double.Parse(txtnum1);
dbl_val2 = double.Parse(txtnum2);
//get the value of the converted variable
//to pass it into the variable in the class
cal.num1 = dbl_val1;
cal.num2 = dbl_val2;
//the condition is, if the radiobutton is clicked,
//the operation of MDAS executes.
if (Radio_Multiplication.Checked)
{
//result:
cal.multiply(); //call a subname in a class for multiplying
}
else if (Radio_Addition.Checked)
{
//result:
cal.add(); //call a subname in a class for adding
}
else if (Radio_Subtraction.Checked)
{
//result:
cal.subtract(); //call a subname in a class for subtracting
}
}
else
{
//the result is:
//if the textbox is empty or has a string value
TextBox3.Text = "Enter a number";
return;
}
//put the result of the MDAS to a textbox.
TextBox3.Text = cal.total.ToString();
}
}
I had a quick look at the link and they don't appear to have declared Information anywhere nor have they indicated that they've overridden anything so...I don't know.
That line, however, is just validating that the information entered into the two text boxes are actually numbers and not anything else that can't be calculated.
There are lots of methods you could use to check those numbers. Options would include, but are not limited to:
if(Int32.TryParse(txtNum1, out int temp1) && Int32.TryParse(txtNum2, out int temp2))
{
do stuff;
}
or
if(txtNum1.All(char.IsDigit) && txtNum2.All(char.IsDigit))
{
do stuff;
}
There are other options, but those two might be worth looking into.
Downloading the sample project, I had a look at what Information refers to. Turns out, it's a class from the Microsoft.VisualBasic namespace, presumably for exposing certain aspects of the VB core library to all .NET languages. You can use it in your program by adding a reference to Microsoft.VisualBasic to your project and adding:
using Microsoft.VisualBasic;
to the top of your code file.
(Personally, I can't imagine that this approach is terribly efficient. It's supposed to take an object and determine if it can be evaluated as a number, and I have no idea what approaches it uses to make that deduction based on any random object. You would probably be better off using one of the alternatives that Benny O'Neill suggests.)

Manipulating an object with a method in another class

Hi I'm very new to c# and I was hoping someone could point me in the right direction. I have created a text box with the value "Total" set to 0 in my main class, and I have created a button "button1_Click" in my "AddFunds" class in which I want it to change the Total value by reading in what the user has in putted "Deposit" putting through a loop and incrementing the "Total". How do I get the AddFunds class to recognize the int Total in my main class?
public void textBox1_TextChanged(object sender, EventArgs e)
{
int Total = new int();
Total = 0;
////string str = Convert.ToString(Total);
////Total.Text = str;
}
public void button1_Click(object sender, EventArgs e)
{
for (int Deposit = 0; Deposit <= 0; ++Deposit)
{
Total = Deposit;
}
}
public void richTextBox1_TextChanged(int initialDeposit)
{
int Deposit = int.Parse(Console.ReadLine());
}
You have some ways of doing that, but remember if this classes you're talking about are forms, they need to exist simultaneously, anything else will end up on you trying to access a null reference.
You can create a public property Total on your main class and pass an instace of Main to AddFund
If the composition is the oposite as the above, and Main holds an instance of AddFund you can make Main inject itself on the other class or pass a Funciotn to AddFund so it can access the value
This one is the only one that doesn't sound like a code smell given the information you provided, abstract your logic to some classes that are not forms and manipulate them on the forms.

How do I get a return value from a Button Click event?

I just started learning C#. I saw an old question of someone trying to make a coca-cola machine and it seemed like a good exercise.
But I got stuck on the money buttons. I can't figure out how I can store the amount of money a button represents in a variable, accessible by the ColaMachine method.
I've got the following code:
using System;
using System.Windows.Forms;
using System.Drawing;
namespace QuickSharp
{
public class ColaMachine : Form
{
public ColaMachine()
{
this.Text = "Cola Machine";
this.Size = new Size(450 , 500);
//Money & Money Buttons
Label Money;
Money = new Label();
Money.Text = "Insert Coins Here:";
Money.Location = new Point(20, 100);
this.Controls.Add(Money);
Button MoneyButton1;
MoneyButton1 = new Button();
MoneyButton1.Text = "€0,05";
MoneyButton1.Location = new Point(28,125);
MoneyButton1.Click += new System.EventHandler(this.MoneyButton1_Click);
this.Controls.Add(MoneyButton1);
Button MoneyButton2;
MoneyButton2 = new Button();
MoneyButton2.Text = "€0,10";
MoneyButton2.Location = new Point(28,165);
MoneyButton2.Click += new System.EventHandler(this.MoneyButton2_Click);
this.Controls.Add(MoneyButton2);
Button MoneyButton3;
MoneyButton3 = new Button();
MoneyButton3.Text = "€0,20";
MoneyButton3.Location = new Point(28,205);
MoneyButton3.Click += new System.EventHandler(this.MoneyButton3_Click);
this.Controls.Add(MoneyButton3);
Button MoneyButton4;
MoneyButton4 = new Button();
MoneyButton4.Text = "€0,50";
MoneyButton4.Location = new Point(28,245);
MoneyButton4.Click += new System.EventHandler(this.MoneyButton4_Click);
this.Controls.Add(MoneyButton4);
Button MoneyButton5;
MoneyButton5 = new Button();
MoneyButton5.Text = "€1,00";
MoneyButton5.Location = new Point(28,285);
MoneyButton5.Click += new System.EventHandler(this.MoneyButton5_Click);
this.Controls.Add(MoneyButton5);
Button MoneyButton6;
MoneyButton6 = new Button();
MoneyButton6.Text = "€2,00";
MoneyButton6.Location = new Point(28,325);
MoneyButton6.Click += new System.EventHandler(this.MoneyButton6_Click);
this.Controls.Add(MoneyButton6);
// Drinks & Drink Buttons
Label Drinks;
Drinks = new Label();
Drinks.Text = "Choose Your Drink:";
Drinks.Location = new Point(315 , 100);
Drinks.AutoSize = true;
this.Controls.Add(Drinks);
Button DrinkButton1;
DrinkButton1 = new Button();
DrinkButton1.Text = "Coca-Cola";
DrinkButton1.Location = new Point(328,125);
this.Controls.Add(DrinkButton1);
Button DrinkButton2;
DrinkButton2 = new Button();
DrinkButton2.Text = "Coca-Cola Light";
DrinkButton2.Location = new Point(328,165);
this.Controls.Add(DrinkButton2);
Button DrinkButton3;
DrinkButton3 = new Button();
DrinkButton3.Text = "Fanta";
DrinkButton3.Location = new Point(328,205);
this.Controls.Add(DrinkButton3);
Button DrinkButton4;
DrinkButton4 = new Button();
DrinkButton4.Text = "Sprite";
DrinkButton4.Location = new Point(328,245);
this.Controls.Add(DrinkButton4);
Button DrinkButton5;
DrinkButton5 = new Button();
DrinkButton5.Text = "Spa Blauw";
DrinkButton5.Location = new Point(328,285);
this.Controls.Add(DrinkButton5);
Button DrinkButton6;
DrinkButton6 = new Button();
DrinkButton6.Text = "Red Bull";
DrinkButton6.Location = new Point(328,325);
this.Controls.Add(DrinkButton6);
//Header & Machine Display
Label Header;
Header = new Label();
Header.Text = "Coca-Cola Machine";
Header.Font = new Font("Arial" , Header.Font.Size +5);
Header.ForeColor = Color.DarkRed;
Header.Location = new Point(132, 20);
Header.AutoSize = true;
this.Controls.Add(Header);
TextBox TextBox1 ;
TextBox1 = new TextBox();
if(InsertedCoins == 0.00)
TextBox1.Text = "Buy Your Ice Cold Drinks Here!";
else
TextBox1.Text = "Inserted Coins: €" + InsertedCoins;
TextBox1.BackColor = Color.Black;
TextBox1.ForeColor = Color.Red;
TextBox1.Font = new Font("Arial" , TextBox1.Font.Size +3);
TextBox1.ReadOnly = true;
TextBox1.Size = new Size(210,300);
TextBox1.Location = new Point(112,50);
// I tried to get the text scrolling here... :)
TextBox1.SelectionStart = TextBox1.Text.Length;
TextBox1.ScrollToCaret();
TextBox1.Refresh();
this.Controls.Add(TextBox1);
}
public double InsertedCoins;
// Money Button Click Events
private void MoneyButton1_Click(object sender, EventArgs e)
{
InsertedCoins = InsertedCoins + 0.05;
}
private void MoneyButton2_Click(object sender, EventArgs e)
{
InsertedCoins = InsertedCoins + 0.10;
}
private void MoneyButton3_Click(object sender, EventArgs e)
{
InsertedCoins = InsertedCoins + 0.20;
}
private void MoneyButton4_Click(object sender, EventArgs e)
{
InsertedCoins = InsertedCoins + 0.50;
}
private void MoneyButton5_Click(object sender, EventArgs e)
{
InsertedCoins = InsertedCoins + 1.00;
}
private void MoneyButton6_Click(object sender, EventArgs e)
{
InsertedCoins = InsertedCoins + 2.00;
}
private static void Main()
{
ColaMachine Scherm;
Scherm = new ColaMachine();
Application.Run(Scherm);
}
}
}
Also, if you have any tips on my general programming (e.g. to make things easier-to-follow for others trying to read my code), please tell me!
When I think about a Coke machine I see a button for each type of drink in the machine, but not buttons for different amounts of money. Maybe you mean a coke costs 50 cents so pressing the coke button I need to charge 50 cents.
Buttons and Event Handlers
When you press a button on the screen it generates a click event. You need to write a method to respond to that click. Any method that we use to respond to an event (generally speaking) is called an event handler. You must tell your program what buttons go with what event handlers. We call this registering the event handler
By convention, if your button is named 'CokeButton' then the event handler associated with that specific button would be named 'CokeButton_ClickHandler'. Or something like that.
General Advice
Think about the thing you are modeling and define things in code to reflect the real world. The things in your model typically will end up as classes, class properties, and class fields. What these things do typically end up as methods w/in the appropriate class. Then you think about how these things interact.
You do not need to figure out everything about a coke machine before you begin writing code. And you should write little bits at a time, test those and then build on what you've tested. Do not write oodles of complex-ish interacting code and then test. You'll end up spinning in circles chasing your tail. Write a little, test a little, repeat. Hear me now and believe me later; write a little, test a little, repeat. Heed this advice now and forever.
So here's how I might think about a Coke Machine. First there is a coke machine itself.
public class CokeMachine {}
A coke machine has a money slot, a return slot, and drink buttons. I can't really put money in a slot, so off hand, I'd say I'll type into a text box. Then I'll click a button and the coke will dispense. I feel like I've defined enough of the model to get started. There's lots of other things about a Coke Machine but I'm not going to worry about them right now.
But I need to know how much each drink costs.
Well, OK. then there must be "CokeCost", "7UpCost", etc. fields. So define them! We'll figure out how and where to use them as we go along.
public class CokeMachine {
Button Coke;
Button 7Up;
Button RootBeer;
TextBox MoneySlot;
double CokeCost = .75;
double 7UpCost = .65;
}
I said the buttons need handlers, so we can write some code shells at least. I expect they'll all work the same way so I'll focus on one for now. Note that as I write code I realize other things that must be dealt with. I'll put in comments, calls to methods that don't exist yet, etc.
public class CokeMachine {
Button Coke;
Button 7Up;
Button RootBeer;
TextBox MoneySlot;
double CokeCost = .75;
double 7UpCost = .65;
// "wiring up" the coke button click event to it's handler.
// We do this in C# by declaring an new EventHandler object (a .NET framework supplied class)
// and we pass in the name of our method as a parameter.
// This new EventHandler is *added* to the button's click event.
// An event can have multiple handlers, that's why we do "+="
// instead of just "=". Otherwise we would have accidentally "unhooked" any
// previously registered handlers.
Coke.Click += new EventHandler(Coke_ClickHandler);
// this is the .NET event handler method signature.
Public void Coke_ClickHandler (object sender, EventArgs args){
if (MoneySlot.Value >= CokeCost) {
DispenseDrink();
// How do I handle returning change? Maybe DispenseDrink() can do that.
}else {
// tell customer to put in more money
}
}
private void DispenseDrink() {
// An empty method is enough to get it to compile so for now that's fine.
// I need to test the Coke_EventHandler logic that I've written so far.
}
}
Now I need to test what I've written so far. After that I need to decide what to focus on next. But realize that when you're writing new code that depends on already written code, if that existing code has not been tested - and now you see errors, you've just made it much harder on yourself. You could have tested when the code is simpler. Now there's more, it's more complex, and will be harder to debug and fix.
Suggestions, Part II
At the risk of messing things up, I offer this folow-up to my original answer:
You can see that every drink button does the same thing, and given the above code we would write the same logic over and over for every button. If anything needs to change we have to change it everywhere.
More General Advice
One Object Oriented Progamming heuristic is encapsulate that which stays the same. You should always be on the lookout for places where things may be candidates for common code.
I want to emphasize that this common button behavior was not immediately obvious to me. Only after I wrote the code above did I get to thinking that all my drink button handlers would start to look the same and I realized that on a real drink machine they actually do behave the same way. My coding spidey-sense told it definitely is a good thing when the code reflects the identifiable behaviors of your real thing (pun intended!).
Refactoring
Actually is a technical term that means reworking existing code to make it more flexible, re-useable, readable, etc. In a word maintainable.
Refactoring should be in your thought processes all the time. But be sure you have a legitimate reason for making any change. Reshaping code is a normal, integral part of software development.
Let's refactor by extracting a method
Public void Coke_ClickHandler (object sender, EventArgs args){
PurchaseDrink("Coke", CokeCost);
}
// now we have a method that stands out and says THIS is how it works
// and a single point of change, rather than ump-teen button handlers.
private PurchaseDrink (string whatKind, double cost) {
// all I did so far is move the code and change "Cokecost" to "cost"
// Now I'm beginning to think I may need to pass "whatKind" to
// DispenseDrink() - but first I need to test the changes I've
// made at this level.
// ***** and since I already tested the code when I 1st wrote it,
// this refactoring will be easier & quicker to test.. GET IT??!! ******
if (MoneySlot.Value >= cost) {
DispenseDrink();
// How do I handle returning change? Maybe DispenseDrink() can do that.
}else {
// tell customer to put in more money
}
}
private void DispenseDrink() {
// An empty method is enough to get it to compile so for now that's fine.
// I need to test the Coke_EventHandler logic that I've written so far.
}
Enumerations
I hate using strings the way I used "Coke" above. Typo's and casing (upper/lower, that is) can cause problems that Visual Studio won't catch. When I have a limited list of things - kinds of drinks - I really like using enumerations. They show up in intellesense and I can use them in switch statements (and research the idea of "type safe"). And what I REALLY like is that they absolutely define in one place all the drink types our program knows about. It's like documentation!
You can store the amount for each button i buttons tag property, and use the following code in your eventhandler to read the amount:
void ValueButton_Click(object sender, EventArgs e)
{
Button button = sender as Button;
if (button == null) return;
if (button.Tag == null) return;
double amount = (double)button.Tag;
// Process the amount here....
InsertedCoins += amount;
}
First think:
You should divide the problem into two classes (class Test and class ColaMachine).
It looks like:
public class ColaMachine : Form
{
public ColaMachine()
{
...
}
}
public class Test
{
private static void Main()
{
ColaMachine Scherm;
Scherm = new ColaMachine();
Application.Run(Scherm);
}
}
Next one: If you want to return a variable that is private, use properties. IC will be a public method (properties). InsertedCoins will be a private variable.
public double IC
{
get
{
return InsertedCoins;
}
set
{
InsertedCoins = value;
}
}
Don't forget, that the machine has a lot of states. You should use the design Pattern, exactly State pattern.

How do I determine if the value of a string variable changed in C#?

I have something to do under a button click (add values to listbox) only if a particular string changes from its previous value. How do I manage this? Below is a sample of my code:
private void button6_Click(object sender, EventArgs e)
{
string x = //some varying value I get from other parts of my program
listBox1.Items.Clear();
listBox1.Items.Add(x + /*other things*/);
}
I can at times have same value for string x from previous value when clicking button6. In such cases I don't want listBox1 to add the item (string x). How to add to listbox only when value of string changes? There's no way to predetermine string x. It gets value when program is running.
Note: adding values to listBox1 every single time and later deleting the duplicates wont work in my program.
Have you considered keeping a copy of the old string value around in a private field, and simply comparing the new value to the old value to see if they match?
For example:
// holds a copy of the previous value for comparison purposes
private string oldString = string.Empty;
private void button6_Click(object sender, EventArgs e)
{
// Get the new string value
string newString = //some varying value I get from other parts of my program
// Compare the old string to the new one
if (oldString != newString)
{
// The string values are different, so update the ListBox
listBox1.Items.Clear();
listBox1.Items.Add(x + /*other things*/);
}
// Save the new value back into the temporary variable
oldString = newString;
}
Edit: As the other answers suggest, there are certainly other, more complicated solutions, like encapsulating all access to the string value in a property, or wrapping the string in a custom class. Some of these alternatives have the potential to be "cleaner", more object-oriented approaches. But they're all more complicated than simply saving the previous value in a field. It's up to you to decide whether your specific use case merits the complicated solution, or a simpler one. Think about long-term maintainability, not what's easier for you to implement right now.
string last = string.Empty;
private void button6_Click(object sender, EventArgs e)
{
string x = //some varying value I get from other parts of my program
if(x!=last)
{
listBox1.Items.Clear();
listBox1.Items.Add(x + /*other things*/);
last = x;
}
}
If this string is super important and gets passed around alot, maybe you should wrap it in a class. The class can hold the string value as a property, but also keep track of when it has changed.
public class StringValue
{
private bool _changed;
public string StrValue{get; set{ _changed = true;}
public bool Changed{get;set;}
}
this is rudimentery of course
I'm not sure I understand completely, but it sounds like you should be using a property to set String x;
string _x = string.Empty;
public string X
{
set
{
if(value != this._x)
{
DoFancyListBoxWork();
this._x = value;
}
}
get
{
return this._x;
}
}
If this is web application, store your last value into session variable. If this is windows application, store it at a class level variable or in singleton class and use this last value for comparison with new value.
On the page load add the current value to viewstate and at the button click check the current value is equal to the value in the view state. If both are equal we can say that the value is not changed.
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
ViewState["CurrentValue"] = Your Value;
}
}
protected void btnSubmit_click(object sender, EventArgs e)
{
if (NewValue== ViewState["CurrentValue"].ToString())
{
lblmsg.Text = "value is not changed..";
return;
}
else
lblmsg.Text = "value is changed..";
}
You can check the detailed article in this link.
Check Control Value is changed or not
First, I'd like to ask you to check most of the other answers. They are more complete, in that they treat more global issues of tracking the changes of a variable.
Now, I'm assuming, from reading the snippet of code you provided, that you need to track if a string was changed by the user. So, in other words, you probably have a TextBox or other kind of control through which the user can change that value. This is where you should focus your attention: just consume the TextChanged event.
If, however, I'm mistaken and your string comes from any other kind of external source, either use the wrapper class suggested by #Ryan Bennett or, if you are using .Net 4, use a dynamic container, which raises a PropertyChanged event whenever any property is changed.

Categories