Calling Parameterized Methods in Other Methods - c#

I don't know if I have chosen a correct headline, but I do hope I have.
I am currently trying to get a better understand of methods in C#, and in doing so I thought that I'd make a simple BankAccount example.
So, what I have is this:
I have three methods:
a method to "deposit" money.
a method to "withdraw" money.
a method to print everything (name, balance).
class BankAccount
{
public string Name
{
get { return _Name; }
set { _Name = value; }
}
private string _Name;
public int Balance
{
get { return _Balance; }
set { _Balance = value; }
}
private int _Balance;
public BankAccount(string name)
{
Name = name;
Balance = 1000;
}
// deposit money
public int Deposit(int balance)
{
Balance += balance;
return Balance;
}
// withdraw money
public int WithDraw(int balance)
{
Balance -= balance;
return Balance;
}
// print to console
public void Print()
{
Console.WriteLine("Owner: " + Name
+ "\nYour current balance is: $" + Balance);
}
}
What I want to do is this:
if I call "deposit" in Main and pass it a value, I want the print method to show me the amount (same goes for "withdraw").
How do I achieve this? I have tried some controle statements, but I don't know how to do this correctly with methods that have parameters?
I hope that someone can shed some light on this issue of mine.

What you can do is overload the method to do more than one thing, for example you can create an overload that takes an int (the balance being subtracted or added) and a string saying which action happening, then you can have this method in the code along with the already existing one
public void Print(int balance, string action)
{
Console.WriteLine("Owner: " + Name
+ "\nYour current balance is: $" + Balance
+ "and you " + action + ": $" + balance);
}
This could be used by passing the string action as "withdrew" or "deposited" depending on which method calls it.
Using this overload allows you to both output the original Print method, if they want to know their balance but never withdrew or deposited, and the new version all depending on which parameters you pass
For more information on overloading see this MSDN page
Example Usage:
public int Deposit(int balance)
{
Balance += balance;
Print(balance, "deposited"); //prints current balance AND action that was completed
return Balance;
}
public void ShowBalance()
{
Print(); //Just prints current balance
}

Related

Can you do calculations in the get/set ? c#

Can you do a calculation in the set clause? and it then returns the total when implemented?`
public decimal TotalCost
{
set
{ this.costTotal = (decimal)prodCost + (decimal)shipping + (decimal)insurance)}
get
{ return this.costTotal}
}
Can you do a calculation in the set clause?
Absolutely. However, in your specific case, it is not clear why would you do that. The point of a setter is to allow users of a class to safely manipulate fields of its objects. This is done using the value keyword. Since you are only interested in calculating a value using existing data, there is no reason to even use a setter. it seems more suitable to do the calculation in a getter only property:
public decimal TotalCost
{
get
{
return (decimal)prodCost + (decimal)shipping + (decimal)insurance);
}
}
A shorter version of the above code:
public decimal TotalCost => (decimal)prodCost + (decimal)shipping + (decimal)insurance;
What others said, but maybe you're looking for a method:
public decimal CostTotal { get; private set; }
(...)
public void SetTotalCost(decimal prodCost, decimal shipping, decimal insurance)
{
this.CostTotal = prodCost + shipping + insurance);
}
I suggest the below code for reading and writing your property.
private decimal totalCost;
public decimal TotalCost
{
get { return totalCost = (decimal)prodCost + (decimal)shipping + (decimal)insurance);}
set { totalCost = value;}
}

Convert object to string in C# [duplicate]

Okay, so I wrote this program from an exercise in a C# programming book (I'm trying to learn here) and it asks for "Override the ToString() method to return all data members".
Have I done this correctly? Or have I just successfully written code that compiles but does nothing? What is the purpose of ToString?
I have spent about 30 minutes looking at other posts on this and haven't figured it out, so I decided to make this.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication297
{
class Program
{
static void Main(string[] args)
{
String name = "Stormtrooper";
Employee s = new Employee(name);
Console.WriteLine("The type of hire is a {0}", s.Name);
Console.WriteLine("The identification number is {0}", s.Number);
Console.WriteLine("The date of hire is {0} ABY", s.Date);
Console.WriteLine("The standard galactic salary is...{0:C}", s.Salary);
}
class Employee
{
private string _name;
private string _number;
private int _date;
private int _salary;
public string Name
{
get
{
return _name;
}
}
public string Number
{
get
{
return _number;
}
}
public int Date
{
get
{
return _date;
}
}
public int Salary
{
get
{
return _salary;
}
}
public Employee(string n)
{
_name = n;
_number = "AA23TK421";
_date = 4;
_salary = 800;
}
}
public override string ToString()
{
return "_name + _number + _date + _salary".ToString();
}
}
}
You are returning a string that just says the phrase _name + _number + _date + _salary.
What you likely wanted to do is build a string using those fields. If you wanted them all mushed together Concat would work, but it would be highly un-readable
public override string ToString()
{
return String.Concat(_name, _number, _date, _salary);
}
However what would be better is to use Format and include labels with the values
public override string ToString()
{
return String.Format("Name:{0}, Number:{1}, Date:{2}, Salary:{3}",_name, _number, _date, _salary);
}
If you are using C# 6 or newer you can use the following cleaner format
public override string ToString()
{
return $"Name:{_name}, Number:{_number}, Date:{_date}, Salary:{_salary}";
}
Which is the exact same logic as the previous String.Format version.
The reason people override the ToString() method is to have a default string representation of your object, usually for display to the user or in a log or console, like this:
Console.WriteLine(yourClassObject);
If you do not override the ToString(), then its default implementation is to return the fully qualified name of your object, like this:
YourNamespace.YourClassName
By changing the inherited implementation (from System.Object), then you can make a nicer (read: prettier) representation, like this:
public override string ToString()
{
return String.Format("This instance of my object has the following: Name = {0}, Number = {1}, Date = {2}, Salary = ${3}", _name, _number, _date, _salary);
}
If you are using C# 6 (or later) use the nameof() method for the property names in the string in case the property names change. You can also use the $"" notation instead of using string.Format().
For example:
public override string ToString()
{
return $"{nameof(Name)}: {_name}";
}
Rather try something like
public override string ToString()
{
return String.Format("Name : {0}, number {1}, date {2}, salary {3}",_name,_number,_date,_salary);
}
But it neads to be part of the class
so
class Employee
{
private string _name;
private string _number;
private int _date;
private int _salary;
.....
public override string ToString()
{
return String.Format("Name : {0}, number {1}, date {2}, salary {3}",_name,_number,_date,_salary);
}
}
Have a look at String.Format Method
Replaces each format item in a specified string with the text
equivalent of a corresponding object's value.
You could try to format the output in a nice format. (not tested, though)
public override string ToString()
{
return string.Format("Name: {0} Number: {1:n0} Date: {2:yyyy-MM-dd} Salary: {3:n2}", _name, _number, _date, _salary);
}
there are a lot of purposes overwriting .ToString(), depending on the context. for example,
some developers like to have nicely formatted object description when doing debug, overwriting .ToString() would allow them to have meaningful description with some identifier (for example, the Id of a object);
Some developers like to put some serialization code into the ToString() method;
Some developers even put some debug code into the .ToString() method, though it might not be a good practice.
it really depending on the context of your needs. you may find some good practices to follow online - believe there are plenty of resources online.
Without overiding ToString, if you tried to "get" the string value of an Employee, e.g.
var employee1= new Employee();
Console.WriteLine(employee1);
What you'd get is:
ConsoleApplication1.Program+Employee
Which provides no information at all to help you (or a UI) display relevant information.
I use
return _name + _number + _date + _salary;
Which defaults to string,
or a more verbose
return "Name:" + _name + " Number:" + _number + " etc...";
class Program
{
static void Main( )
{
int Number = 10;
Console.WriteLine(Number.ToString());
Customer cc = new Customer();
cc.FirstName = "Rakibuz";
cc.LastName = "Sultan";
Console.WriteLine(Convert.ToString(cc));
}
}
public class Customer
{
public string FirstName;
public string LastName;
public override string ToString()
{
return FirstName + " " + LastName;
}
}

How to find specific value in list objects, bank deposit

I have a list of customers who owns three bankaccount each (credit, check, retirement) Each bankaccount is a seperate class, with a seperate withdraw method inside. I choose a person in a list (Visual studio) and can by clicking on them see their bankaccount in another list. Now i want to choose one of their account and deposit Money into it, and it is now i get stuck. The money are just beeing depostit to the first bankaccount in the list(index 0)...
I guess i have to compare the account that the customer want to deposit to with the right objects namn in my list (the right account), but cant figure out how i should write this!
the account could also be in different order so i cant just say saving = [0], check [1], retiremet [2],
This is how i call the method
validCustomer = (Customer)lstBankKunder.SelectedItem;
if (radioButtonSaving.IsChecked == true)
{
savingAccount = new SavingsAccount();
savingAccount.DepositMoney(299, valdCustomer);
lstKonton.ItemsSource = null;
lstKonton.ItemsSource = valdCustomer.myBankAccount;
}
And the SavingsAccount class
public override void DepositMoney(int money, Customer validCustomer)
{
savingsaccount = new SavingsAccount();
var item = validCustomer.myBankAccount[savingsaccount.Balance];
item.Balance += money;
validCustomer.myBankAccount[savingsaccount.Balance] = item;
}
I think the error is in your DepositMoney method. You are creating a new savings account, every time the method is called and I guess, that the initial balance is 0. But then you are using this balance to select a bank account:
valdCustomer.myBankAccount[savingsaccount.Balance]
With this logic this would always be the first account in the list.
There are more than one issue with your code. You are creating unnecessary objects of SavingsAccount class at various places.
You haven't shared the code of Customer class so I am not sure what is the type of myBankAccount property.
You need a good way to select a proper account from the customer's multiple account based on the accounttype and then call deposit or withdraw method on that account.
You can use enum for this. Let say you have an enum AccountType as following which identifies the type of account.
public enum AccountType
{
Credit,
Check,
Retirement
}
And then have a property of AccountType in the Account.
public class BankAccount
{
protected double balance;
protected int accountNumber;
protected AccountType accountType;
public BankAccount(int accountNumber, AccountType accountType)
{
this.accountNumber = accountNumber;
this.accountType = accountType;
}
public virtual void DepositMoney(double amount)
{
this.balance += amount;
}
public virtual void WithdrawMoney(double amount)
{
this.balance -= amount;
}
public double Balance
{
get
{
return this.balance;
}
}
public AccountType AccountType
{
get
{
return this.accountType;
}
}
public override string ToString()
{
var output = new StringBuilder();
output.Append(string.Format("Account Number : {0}{1}", this.accountNumber, Environment.NewLine));
output.Append(string.Format("Account Type : {0}{1}", this.accountType, Environment.NewLine));
output.Append(string.Format("Account Balance : {0}{1}", this.balance, Environment.NewLine));
return output.ToString();
}
}
And in Customer class you can have List of accounts to represent the accounts belonging to that customer.
public class Customer
{
private List<BankAccount> accounts;
public Customer()
{
this.accounts = new List<BankAccount>();
}
public string Name {get;set;}
public List<BankAccount> Accounts
{
get
{
return this.accounts;
}
}
public override string ToString()
{
var output = new StringBuilder();
output.Append(string.Format("Customer Name : {0}{1}", this.Name, Environment.NewLine));
output.Append(string.Format("Accounts details {0}", Environment.NewLine));
foreach(var account in this.accounts)
{
output.Append(account.ToString());
}
return output.ToString();
}
}
And then you can locate specific type of account of customer and perform deposit or withdraw operation on it as following.
var checkAccount = customer.Accounts.FirstOrDefault(acct => acct.AccountType == AccountType.Check);
if(checkAccount != null)
{
checkAccount.DepositMoney(3000);
}
FirstOrDefault is an extension method which is part of LINQ. You need to add using System.Linq; in the using directives of the code file whereever you are using it.
Note : The names of class, methods and properties are different in my answer then your class names.
I hope this helps you resolve your issue.
EDIT : Edited the answer to have List of accounts in Customer class instead of Dictionary.

Prevent creation of an account with < 0 OR > 10,000

I currently have a program that makes bank accounts and stores them but I am trying to add code to prevent a user from setting up an account with a negative balance or a balance that exceeds 10,000.
I have declared private decimal balance = 0; in order to set the initial balance to 0 for everyone, it is then later on that they enter the amount they wish to store. What I am trying to do is stop people from creating their account with < 0 OR > 10,000
This is the IF statement I have so far
public virtual bool BalanceRange(decimal amount)
{
if ((balance < 0) || (balance > 10000))
{
return false; //OR message "Amount Not Allowed";
}
this.balance = amount;
return true;
}
The point of this IF statement is to check the amount that the user wishes to store in their bank account, the number is inputted within the Main method as shown below:
public static void Main()
{
CustomerAccount test = new CustomerAccount("Fred", 11000);
Console.WriteLine(test.GetName());
Console.WriteLine(test.GetBalance());
}
What this does is create an account with the Name of Fred and with the amount 11,000. My IF statement should reject the creation of this account as the amount is exceeding the amount I set the if statement to check for(10,000) but that does not seem to be happening and I am not sure why
It may be caused by this. This is the class used for the GetBalance() test so I was thinking that my IF statement needs to be placed within this.
public virtual decimal GetBalance()
{
return this.balance;
}
The constructor:
public interface IAccount
{
bool PayInFunds(decimal amount);
bool WithdrawFunds(decimal amount);
bool BalanceRange(decimal amount);
decimal GetBalance();
string RudeLetterString();
string GetName();
bool SetName(string inName);
}
You're checking the balance before you set it, so it'll be always 0. The check passes, and then you set the illegal number. Check the amount parameter, not the balance field.
public virtual bool BalanceRange(decimal amount)
{
if ((amount < 0) || (amount> 10000))
{
return false; //OR message "Amount Not Allowed";
}
this.balance = amount;
return true;
}
I'm afraid I cannot comment, so this way to ask, where do you even call the BalanceRange method?
I'd expect if even then somewhere in the constructor, but you can't call the constructor, which then rejects to create a object.
You could try something like this in your class with a privat constructor:
public static CustomerAccount AccountFactory(string name, int amount)
{
if ((balance < 0) || (balance >
return null; //OR message "Amount Not Allowed";
return new CustomerAccount(name, amount)
}

Why am I getting a "the name does not exist in the current context" error on this C# program?

Why am I getting a "the name does not exist in the current context" error on this C# program?
Here is my class file:
namespace Exercise8
{
class Park
{
Park aPark = new Park();
private string name;
public string Name
{
get
{
name = Console.ReadLine();
return name;
}
set
{
}
}
private string location;
public string Location
{
get
{
location = Console.ReadLine();
return location;
}
set
{
}
}
private string facilityType;
public string FacilityType
{
get
{
facilityType = Console.ReadLine();
return facilityType;
}
set
{
}
}
private string facilitiesAvailable;
public string FacilitiesAvailable
{
get
{
facilitiesAvailable = Console.ReadLine();
return facilitiesAvailable;
}
set
{
}
}
private double fee;
public string sFee;
public double Fee
{
get
{
fee = double.Parse(sFee);
sFee = Console.ReadLine();
return fee;
}
set
{
}
}
private int noOfEmployees;
public string sNoOfEmployees;
public int NoOfEmployees
{
get
{
noOfEmployees = int.Parse(sNoOfEmployees);
sNoOfEmployees = Console.ReadLine();
return noOfEmployees;
}
set
{
}
}
//variables for Cost Per Visitor.
//noVisitors will be used in Calculate Revenue
public double costPerVisitor;
public double annualBudget = 200000;
public double noVisitors = 10000;
public double CalculateCostPerVisitor(double annualBudget, double noOfVisitors)
{
//divide annual budget by number of visitors
return costPerVisitor = annualBudget / noVisitors;
}
//Calculate Revenue
public double revenue;
public double CalculateRevenue(double noOfVisitors,double fee)
{
//No of Visitors times Fee
revenue = noVisitors * fee;
return revenue;
}
public override string ToString()
{
return "Name of park: " + this.Name + "\nLocation: " + this.Location + "\nFacility Type: " + this.FacilityType + "\nFacility Fee: " + this.Fee + "\nNumber of employees: " + this.NoOfEmployees +
"\nNumber of visitors recorded in the past 12 months: " + this.noVisitors + "Annual Budget: " + this.annualBudget;
}
}
}
Here is my program:
namespace Exercise8
{
class Program
{
public static void main (String [] args)
{
//Instantiate Objects
Park aPark = new Park();
//Call Methods
Console.WriteLine("Name of park: " + aPark.Name + "; Location of park: " + aPark.Location + "; Type of park: " + aPark.FacilityType);
Console.WriteLine("Name of park: " + aPark.Name + "; Location of park: " + aPark.Location + "; Facilities available: " + aPark.FacilitiesAvailable);
Console.WriteLine("Annual cost per visitor: " + CalculateCostPerVisitor());
Console.WriteLine("Revenue: " + CalculateRevenue());
//Below should hopefully return To String
Console.WriteLine(aPark.ToString());
}
}
}
And these are the errors I'm seeing:
The name 'CalculateCostPerVisitor' does not exist in the current context
The name 'CalculateRevenue' does not exist in the current context line
Those methods are defined for objects of type Park, but you're trying to access them from inside Program without qualification or an object of type Park.
For static methods, you would need to qualify them with the class name. But these methods are not static.
For instance methods, you need to call them on a particular instance. You have an instance aPark, but you aren't using it when you tried to call its methods.
The methods are defined as instance methods on the Park class type, so you need to call the method with a reference to an instance of Park. Additionally, each method takes 2 parameters, so you'd have to provide them at the time you call the methods:
Console.WriteLine("Annual cost per visitor: " + aPark.CalculateCostPerVisitor( ... /* actual parameters here */));
Console.WriteLine("Revenue: " + aPark.CalculateRevenue( ... /* actual parameters here */));
However, since you've defined annualBudget, noOfVisitors, and fee as fields of your Park class, I think it's likely that you never really intended these values to passed in as parameters—or at the very least you're confused about whether these should really be parameters or if the class should calculate the result from the field values.
I'd recommend you remove these parameters, and simply calculate the results from the field values:
public double CalculateCostPerVisitor()
{
//divide annual budget by number of visitors
this.costPerVisitor = this.annualBudget / this.noVisitors;
return this.costPerVisitor;
}
public double CalculateRevenue()
{
//No of Visitors times Fee
this.revenue = this.noVisitors * this.fee;
return this.revenue;
}
...
Console.WriteLine("Annual cost per visitor: " + aPark.CalculateCostPerVisitor());
Console.WriteLine("Revenue: " + aPark.CalculateRevenue());
Not entirely relevant to the question, but there are a few other things wrong (or at least very strange) about your class:
Park aPark = new Park();
You are creating new instance of Park inside every Park, this is bound to lead to a stack overflow error if you try to create a single instance. You should remove this line from your class file.
name = Console.ReadLine();
You are reading from the console every time you try to get the value from a property. This is wrong on many levels. All of your properties should just get / set private values and try to do as little work as possible. If you want to allow the user to specify the name in the console, that should be done in your Main method like this:
aPark.Name = Console.ReadLine();
fee = double.Parse(sFee);
sFee = Console.ReadLine();
I'm not entirely sure what's going on here, but it's backwards. You need to read the input from the console first, then try to parse it. And again, it should be done in the Main method, look like this:
string sFee = Console.ReadLine();
aPark.Fee = double.Parse(sFee);
Once you've corrected the properties following the above steps, you can drop the private backing fields and dramatically simplify your code using automatic properties, like this:
public string Name { get; set; }
You should generally avoid public fields. If you keep costPerVisitor as a member of your class, you should probably make it a property, like this:
public double CostPerVisitor { get; set; }
Problem 1:
call the method with a reference to an instance of Park
aPark.CalculateCostPerVisitor(argument1, argument2);
Problem 2:
Also, CalculateCostPerVisitor() needs to have two arguments. There is not CalculateCostPerVisitor() method in your class.
You have
public double CalculateCostPerVisitor(double annualBudget, double noOfVisitors)
public double CalculateRevenue(double noOfVisitors,double fee)

Categories