I've been trying to learn some C# by creating a basic banking application that allows a user to add a current or savings account. If it's a current account then it multiplies the starting balance by 0.2 and if its a savings, then it multiples by 0.6. When they add an account, the application should save it to a list and finally display all the account names. So far I have a the form which allows the user to add an account called AddAccount.cs. I then have an Account.cs which should set the account and then a AccountList.cs which adds it to a list.
What I need help with:
How do I pass the new account details and set them in the Account.cs?
How then to add the account to the list and display the name of the Account?
Account.cs:
abstract class Account
{
public string accName, accId, accType;
public double balance;
public void setValues(string name, string id, double bal, string type)
{
this.accName = name;
this.accId = id;
this.balance = bal;
this.accType = type;
}
}
class CurrentAccount : Account
{
public double interst()
{
return balance * 0.2;
}
}
class SavingsAccount : Account
{
public double interst()
{
return balance * 0.6;
}
}
AddAccount.cs:
private void btn_AddAccount_Click(object sender, EventArgs e)
{
string name, id, type;
double balance;
name = input_AccountName.Text;
id = input_AccountNo.Text;
balance = Convert.ToDouble(input_StartBalance.Text);
if (radio_CurrentAccount.Checked)
{
type = "C";
}
else
{
type = "S";
}
//closes the form when clicked
this.Close();
}
AccountList.cs:
class AccountList
{
private List<Account> accountlst;
public List<Account> AccountLst
{
get { return accountlst; }
}
}
Please let me know if I'm completely wrong. Even the slightest bit of help would be appreciated.
Well assuming that if type is "C" then you create an object of type current account and if type is "S" then you create a savings account it would look something like this (by the way im going to do this in pseudo-code):
if (type is C)
Create new CurrentAccount object
call setValues(name, id, bal, type) //these are the local variable you created in AddAccount.cs
getAccountlst().add(CurrentAccount object you created) //adds to list
else
Create new SavingsAccount object
call setValues(name, id, bal, type)
getAccountlst().add(SavingsAccount object you created) //adds to list
By the way 2 problems, since you never initialized the accountlst object inside AccountList.cs by calling the new operator, it is set to null, so when you call getAccountlst() it will return a null object and if you try to add to it you will get a null pointer exception! And the pther problem, Since your AccountList.cs has to be initialized with new operator, you can lose your information inside your list, to fix this you can do something like:
static class AccountList {
List<Account> accountList = new List<Account>();
public List<Account> Accountlst {
get {
return accountList;
}
}
}
Now to add to your list all you have to do is AccountList.Accountlst.add(Account object here);
Related
My hypothetical scenario:
In the New World Order, the single government mandates that all the banks should provide the same rate of interest to its customers. So all the bank should agree the rate of interest. Additionally a bank needs to have a policy
where it is open to changing(either increasing or decreasing) the interest
or not. If (at least) one bank is not open to changing the rate of interest, rate must not be modified until successful negotiations.
My C# program would look like below
namespace NewWorldOrder
{
public class Bank
{
public static float rate;
private bool allow_rate_modification;
private string bankname;
// Property
public string Bankname
{
// Assume some Business Logic is added to filter values
// Omitting those for brevity
get => bankname;
set => bankname = value;
}
// Property
public bool AllowRateModification
{
// Assume some Business Logic is added to filter values
// Omitting those for brevity
get => allow_rate_modification;
set => allow_rate_modification = value;
}
static Bank()
// To set the static field at runtime
{
// In actual case, this value may be initialized from a db
// Again doesn't matter how it is initialized.
rate = 4.5f;
}
// The ctor
public Bank(string bank_name_, bool allow_modification)
{
Bankname = bank_name_;
AllowRateModification = allow_modification;
}
}
class Program
{
static void Main(string[] args)
{
Bank rbs =new Bank("Royal Bank of Scotland",true);
Bank lloyds = new Bank("LLoyds", true);
Bank hsbc = new Bank("HSBC", false);
Bank.rate = 4.7f; // This should not happen as HSBC is not open to rate change
// Irrelevant Stuff
// ...
// ...
}
}
}
Long story short :
How can a static (class) property bind to one particular (usually boolean) instance property in all the instances. Or is there another logical approach
in C# by which this can be done?
Note: I am (very) new to C# , so please forgive me if this is complete blunder
Sounds like you need a list, linq can help you query it
var list = new List<Bank>()
{
new Bank("Royal Bank of Scotland", true),
new Bank("LLoyds", true),
new Bank("HSBC", false)
};
if (list.All(x => x.AllowRateModification))
{
// all banks Allow Rate Modification
}
You could use a class to manage the banks
public class Exchange
{
public List<Bank> Banks { get; set; } = new List<Bank>();
public void NegotiateRates()
{
while (!CanModifyRates)
{
// to the rate stuff in here
}
}
public bool CanModifyRates => Banks.All(x => x.AllowRateModification);
}
...
private static void Main()
{
var exchange = new Exchange();
exchange.Banks.Add(new Bank("Royal Bank of Scotland", true));
exchange.Banks.Add(new Bank("LLoyds", true));
exchange.Banks.Add(new Bank("HSBC", false));
exchange.NegotiateRates();
}
Additional Resources
List Class
Represents a strongly typed list of objects that can be accessed by
index. Provides methods to search, sort, and manipulate lists.
Enumerable.All(IEnumerable, Func) Method
Determines whether all elements of a sequence satisfy a condition.
Edit to save you from reading through this whole post
tldr: an object's fields should not be static unless you want all instances of that object to have the same value for that field
I'm trying to create and populate an ArrayList of Blog objects. I do know the generic way do this:
create ArrayList of Blogs
loop (some condition)
create new Blog
add this Blog to AL
However, when I attempt to do so within the while(datareader.read()) loop, all of the elements in the ArrayList are exactly the same Blog. Specifically, I end up with an ArrayList filled with multiple pointers to the very last Blog object from the database table. Here is my code:
public static ArrayList AllBlogs()
{
SqlDataReader dr = anonPage.ExecuteReader("SELECT * FROM Kristina_Blogs");
ArrayList allBlogs = new ArrayList();
if (dr.HasRows)
{
while (dr.Read())
{
Blog b = new Blog();
//grab a row from Kristina_Blogs and assign those attributes to b
b.setTitle(dr["title"].ToString());
b.setMessage(dr["message"].ToString());
b.setId(dr["id"]);
allBlogs.Add(b);
}
}
dr.Close();
return allBlogs;
}
As I said before, the result of this is an ArrayList filled with pointers to the very last blog from the Kristina_Blogs table. I imagine the ArrayList allBlogs looks like [b, b, b, ... b] and therefore they ALL get updated when I say b.setTitle() etc. But how can this be the case if I am creating a NEW Blog object at the beginning of each iteration?
Here is some extra info that you don't have to read but it might clear up some confusion about the structure of the problem:
Blog object has id, title, and message fields and their respective getter/setters
Kristina_Blogs is a table representing these blogs with columns for id, title, message
The suggestions say to include a tag for my DB engine but I can't find a tag for it: Microsoft SQL Server Management Studio
This code works perfectly when I use an ArrayList of Strings instead of Blogs
Edit: Including the code from Blog class
public class Blog
{
public App myApp;
public static string Title;
public static string Message;
public static int Id;
//constructors
public Blog() { }
public Blog(App App) { this.myApp = App; }
//all getters and setters look like this
public string getTitle() { return Title; }
public void setTitle(string t) { Title = t; }
}
The main problem you have, as I mentioned in comments is your member variables are static, so when you set the value, they change in all instances. you should change your code this way:
public class Blog
{
public int Id { get; set; }
public string Title { get; set; }
public string Message { get; set; }
}
And fill your list this way, don't forget to add using System.Linq;:
var result = new List<Blog>();
var connection = #"your connection string";
var command = "SELECT * FROM Kristina_Blogs";
var adapter = new System.Data.SqlClient.SqlDataAdapter(command, connection);
var dataTable = new DataTable();
//Get data
adapter.Fill(dataTable);
dataTable.Rows.Cast<DataRow>().ToList()
.ForEach(row =>
{
var b = new Blog();
b.Id = row.Field<int>("Id");
b.Title = row.Field<string>("Title");
b.Message = row.Field<string>("Message");
result.Add(b);
});
return result;
Note:
When you create a member static, it is shared between all instances of that calss.
In C# you can use property to get or set values, you don't need to setX or setY, when you get the value of a property, the get code of that property will execute and when you assign a value to a property the set part of it will execute. you can define properties this way:
Property:
private int id;
public int Id
{
get
{
return id;
}
set
{
id = value;
}
}
or more simple:
public int Id { get; set; }
All of the fields in your Blog class are static, meaning they're shared between all object instances. You want them to be instance field (meaning not static) so that each object has its own copy of each of those values.
Remove the static attributes from your class:
public class Blog
{
public App myApp;
public String Title;
public String Message;
public int Id;
//constructors
public Blog() { }
public Blog(App App) { this.myApp = App; }
//all getters and setters look like this
public String getTitle() { return Title; }
public String getMessage() { return Message; }
public void setTitle(String t) { Title = t; }
public void setMessage(String m) { Message = m; }
}
When you use static variables, all instances of an object will contain the same values in those variables. By removing the static keyword, you are allowing different instances of the object to hold different values.
Now, every time you create a blog object, that object's Title and Message etc, will contain its own information.
I would make a quick method to prevent null value from throwing error
public static string GetSafeString(SqlDataReader reader, int index)
{
if (!reader.IsDBNull(index))
return reader.GetString(index);
else
return string.Empty;
}
Replace this code:
while (dr.Read())
{
Blog b = new Blog();
//grab a row from Kristina_Blogs and assign those attributes to b
b.setTitle(dr["title"].ToString());
b.setMessage(dr["message"].ToString());
b.setId(dr["id"]);
allBlogs.Add(b);
}
With This Code:
while (dr.Read())
{
Blog b = new Blog();
//grab a row from Kristina_Blogs and assign those attributes to b
b.setId(dr.GetInt32(0));
b.setTitle(GetSafeString(dr, 1);
b.setMessage(GetSafeString(dr, 2);
allBlogs.Add(b);
}
Where the number is the index of field in the record and assuming "id" is an integer. Also consider moving creation of "Blog" object outside of loop and just change values.
I am trying to create a program that mimics an ATM. In my program, I need to check if the string that a user enters matches the Name property of any objects within a list of objects. If it does not match, then the account is automatically added with some other default values. If it does match, then I need to set the variables that are accessed on another form to the properties of that account object. Additionally, those properties will need to be updated from the other form, so that the object is kept current. I think that I can figure out how to update those properties, but I am having difficulty with trying to set the variables to the current account, more specifically, how to access the properties of the matching account. My class constructor is as follows:
class Account
{
private string name;
public string Name
{
get
{
return name;
}
set
{
name = value;
}
}
private int acctNum = 0;
public int AcctNumber
{
get
{
return acctNum;
}
set
{
acctNum = value;
}
}
//initialize the CheckBalance value to 100.00
private decimal checkBalance = 100.00M;
public decimal CheckBalance
{
get
{
return checkBalance;
}
set
{
checkBalance = value;
}
}
public Account(string Name)
{
this.Name = Name;
}
private decimal saveBalance = 100.00M;
public decimal SaveBalance
{
get
{
return saveBalance;
}
set
{
saveBalance = value;
}
}
}
This works out just fine, as the only constructor that I need is the Name property, while the other properties are automatically set to a base value. The list and relevant code that I currently have are as follows:
//variable that will be used to check textbox1.Text
string stringToCheck;
//array of class Account
List<Account> accounts= new List<Account>();
public MainMenu()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
//set value to user's input
stringToCheck = textBox1.Text;
//set a var that only returns a value if the .Name already exists
var matches = accounts.Where(p => p.Name == stringToCheck);
//check through each element of the array
if (!accounts.Any())
{
accounts.Add(new Account(stringToCheck));
}
else if (matches != null)
//set variables in another form. not sure if these are working
Variables1.selectedAccount = ;
//is this calling the CheckBalance of the instance?
Variables1.selectedCheckBalance = accounts[i].CheckBalance;
//same thing?
Variables1.selectedSaveBalance = accounts[i].SaveBalance;
//switch to form
AccountMenu acctMenu = new AccountMenu();
this.Hide();
acctMenu.Show();
}
In the above code, the "else if (matches != null)" is more of a filler, since I am not sure what to use. Of course, I also need to re-write the portion "if (!accounts.Any())" because once the list is populated with at least one object, this code will never occur again. So, really, I just need to know how to check for a matching account and how to access the properties of that account so that I can set the Variables1 properties to match. Thanks for any help!
If it works for your particular situation, var account = accounts.FirstOrDefault(p => p.Name == stringToCheck) will give you the first account in the collection that matches the expression or null if nothing exists.
check if account != null to ensure you do not get a null reference exception when trying to get property values.
Then, use account.CheckBalance to get the property value for that particular account.
I may not be fully understanding the question and cannot comment because I do not have a 50 reputation : (
I'm doing a simple program to add a student(with ID,Name) to a List, then to search Student by ID through session.
Add Student Module is like below,
protected void addStudent(object sender, EventArgs e)
{
List<Student> thisstdlist = new List<Student>();
thisstdlist = (List<Student>)Session["stdlist"];
thisstdlist.Add(new Student(txtsid.Text,txtsname.Text));
Session["stdlist"] = thisstdlist;
Response.Redirect("Home.aspx");
}
Search Student Module is Like Below,
protected void searchStudent(object sender, EventArgs e)
{
foreach (Student element in (List<Student>)Session["stdlist"])
{
if(element.getID().Equals(txtstdid.Text)){
txtstdname.Text = element.getName();
}
}
}
Student Class is like below,
public class Student
{
private String Name;
private String ID;
public Student(String sid, String sn) {
this.Name = sn;
this.ID = sid;
}
public String getName() {
return this.Name;
}
public String getID()
{
return this.ID;
}
}
But when I added students, for ex: 100,John and Search by 100 it gives me no result. Please can anyone show me the mistake or the correct way of doing this.
are you setting breakpoints and actually checking what the values of these lists and what is actually stored in the session?
.Equals() is not doing what you think it is
try :
foreach (Student element in (List<Student>)Session["stdlist"])
{
if(element.ID == txtstdid.Text){
txtstdname.Text = element.getName();
}
}
The add Student module won't initialize the student list correctly - you are creating a new List<Student> and then throwing the new list away with the next line assignment. I would go with something like:
var thisstdlist = (List<Student>)Session["stdlist"];
// If a key isn't found in Session, it will be null ..
if (thisstdlist == null)
{
// i.e. only re-initialize if it was missing from session
thisstdlist = new List<Student>();
// You don't need to continually reassign the session variable
Session["stdlist"] = thisstdlist;
}
// Adds to the list; now that Session also has a reference to the same list
thisstdlist.Add(new Student(txtsid.Text,txtsname.Text));
As per the comment, note that c# has automatic (albeit mutable) properties - you don't need the Java-style getters and setters.
public class Student
{
public Student(string sid, string sn)
{
Name = sn;
ID = sid;
}
public string Name
{
get;
set;
}
public string ID
{
get;
set;
}
}
Also, in .Net, == for strings is overridden to test values (unlike Java's reference equality for strings), so you can rewrite the comparison as:
if (element.ID == txtstdid.Text)
{
txtstdname.Text = element.Name;
}
Re : foreach - I guess means that you are using the List in a Dictionary (HashMap) fashion - if you use Dictionary instead of List - this will allow you do remove the foreach in favour of:
// addStudent ...
var txtstdname = new Dictionary<string, Student>();
// ...
txtstdname.Add(txtsid.Text, new Student(txtsid.Text,txtsname.Text))
// searchStudent ...
Student element = null;
if (txtstdname.TryGetValue(out element))
{
txtstdname.Text = element.Name();
}
I have a Linq to Entities query and I want to select some specific columns and store the new object into a pre-defined object. However, I'm getting the error
<object> does not contain a constructor that takes 0 arguments.
Not sure what is wrong here...
Also not sure if this is the best way or if using anonymous type is better instead of creating a payroll object.
Linq Query
public Payroll GetTestCasePayroll(decimal testScenarioID) //not sure if object is correct return
{
Payroll instance = (from o in DbContext.UI_OnDemandCheckHeader
where o.TestScenarioID == testScenarioID
select new Payroll(o.PayEntityCode, o.PayrollYear, o.PayrollNumber)).First();
//{ PayEntityCode = , PayrollYear = o.PayrollYear, PayrollNumber = o.PayrollNumber }).First();
return instance;
}
Payroll object
class Payroll
{
private string _payEntityCode;
private decimal _payrollYear;
private string _payrollNumber;
public Payroll(string payEntityCode, decimal payrollYear, string payrollNumber)
{
PayEntityCode = payEntityCode;
PayrollYear = payrollYear;
PayrollNumber = payrollNumber;
}
public decimal PayrollYear
{
get { return _payrollYear; }
set { _payrollYear = value; }
}
public string PayEntityCode
{
get { return _payEntityCode; }
set { _payEntityCode = value; }
}
public string PayrollNumber
{
get { return _payrollNumber; }
set { _payrollNumber = value; }
}
Your Payroll class needs a constructor that takes no parameters e.g.
Public Payroll() { }
Linq works by creating an empty instance of the output class and then using the setters on each of the properties. It does not use anything but an empty constructor.