I am curious to know what is the proper way of writing a constructor or rather when do I write it this way or the other.
I would also like to know why would you change the name of the field in the construcor, like I did in the first constructor with the field address.
Thank you for your help.
For example lets say you have a class Shipment with four fields: String item, Double price, String address, Double weight.
class Shipment
{
private string item;
private double price;
private string address;
private double weight;
public Shipment(string item, double price, string addr, double weight)
{
this.item=item;
this.price=price;
address=addr;
this.weight=weight;
}
public Shipment()
{
item="Football jersey";
price=35.99;
address="8520 Washington Dr.Toledo, OH 43612"
weight=0.400;
}
}
I would change the default constructor definition like this,
public Shipment : this ("Football jersey", 35.99, "8520 Washington Dr.Toledo, OH 43612", 0.400 )
{
}
This reuses the parameterized constructor and makes your code a bit more concise.
The rest of your code is ok. The usage of this in the constructor is pretty standard and it prevents you from inventing other names for the constructor arguments (ex - addressParams).
Related
I have a code that uses inheritance in C# and I seem to have lost my price variable along the way. How can I get my price variable to work with the child classes when the parent class doesn't have it as a parameter? Please note: this has been submitted and marked, I'm not looking for extra marks, just trying to improve my learning.
Not sure if this is enough code to help, but I didn't want to flood the screen. Basically the PerformBuyStock method is in the program file and it records the price variable along with the quantity. However once the transaction is executed through the transaction class, because it doesn't have 3 parameters (stock, price, quantity) like the StockPurchaseTransaction class, then the price reverts to 0 when it executes printSummary. How do I get the price variable to still be there without changing the Transaction class? Thank you for any help you may be able to provide.
public abstract class Transaction
{
protected readonly Stock _stock;
protected readonly decimal _price;
protected readonly int _quantity;
protected readonly string SummaryLine;
public Transaction(Stock stock, int quantity)
{
_quantity = quantity;
_stock = stock;
SummaryLine = ($" - {_stock.Name} x {_quantity} #${_price}");
}
}
public class StockPurchaseTransaction : Transaction
{
public StockPurchaseTransaction(Stock stock, decimal price, int quantity) :base(stock, quantity)
{
stock = _stock;
price = _price;
quantity = _quantity;
}
public override void PrintSummary()
{
Console.WriteLine($"BUY {SummaryLine}");
}
}
private static void PerformBuyStock(Warehouse toWarehouse)
{
Stock stock = FindStockItem(toWarehouse);
if (stock == null) return;
int quantity;
decimal price;
Console.WriteLine($"Quantity of {stock.Name} purchased:");
quantity = Convert.ToInt32(Console.ReadLine());
Console.WriteLine($"Price per item purchased: ");
price = Convert.ToDecimal(Console.ReadLine());
StockPurchaseTransaction purchase;
purchase = new StockPurchaseTransaction(stock, price, quantity);
toWarehouse.ExecuteTransaction(purchase);
purchase.PrintSummary();
}
public void ExecuteTransaction(Transaction transaction)
{
_transactions.Add(transaction);
transaction.Execute();
}
the price reverts to 0 when it executes printSummary. How do I get the price variable to still be there without changing the Transaction class?
The issue is that the base class constructor is what sets the SummaryLine field, which is used to print the summary later. But at the time that that field is set, the _price field hasn't been initialized to the caller-provided value (indeed, it never is). It still has the default value of 0.
It certainly doesn't help that in the subclass constructor, you aren't even assigning the field correctly. The variables are on the wrong side of each assignment operator. As it happens, if you'd put them on the correct side, you'd have gotten a helpful compile-time error message explaining that the subclass constructor isn't allowed to assign a value to the readonly fields in the base class.
Anyway…
To fix it without changing the Transaction class? Well, the only way to do that is to add code in your subclass StockPurchaseTransaction that mirrors the code in the base class, but fixes the bugs that exist in it.
That might look something like this:
public StockPurchaseTransaction(Stock stock, decimal price, int quantity) :base(stock, quantity)
{
// To be clear: these three assignments are incorrect, and accomplish nothing
stock = _stock;
price = _price;
quantity = _quantity;
// This assignment would "fix" the problem, but it's not really the right way,
// and the field is readonly so this won't actually compile
SummaryLine = ($" - {stock.Name} x {quantity} #${price}");
}
Except that won't work, because unlike the assignments before it, the correct assignment of SummaryLine won't work as long as the base class field is readonly.
But really, the base class constructor is what's wrong, and that's where the fix ought to go:
public Transaction(Stock stock, int quantity, decimal price)
{
_quantity = quantity;
_stock = stock;
_price = price;
SummaryLine = ($" - {_stock.Name} x {_quantity} #${_price}");
}
Of course, then you'd need to add the price parameter to the base class constructor call:
public StockPurchaseTransaction(Stock stock, decimal price, int quantity)
: base(stock, quantity, price) { }
Note that if you do it that way, then the subclass constructor has nothing to do. All of the real work is done in the base class.
Bottom line, it's impossible to do what you are literally asking. The base class has bugs in it, and because of the readonly fields, you can't correct for those bugs in the subclass. They have to be fixed in the base class.
Thanks in advance guys. I am quite new to coding so please be patient. Below is a piece of code I am working on. This is the complete code below. It's as follows:
using System;
public class Product
{
private string name;
private decimal price;
public string Name
{
get
{ return name; }
set
{ name = value; }
}
public decimal Price
{
get
{ return price; }
set
{ price = value; }
}
public Product(string name, decimal price)
{
this.name = name;
this.price = price;
}
}
In the page load method, an object is instantiated and the constructor is called as follows:
private void Page_Load(object sender, EventArgs e)
{
Product saleProduct = new Product("Kitchen Garbage", 49.99M);
}
When the product is created, the constructor is initialised, with the above values. Now if you look in the constructor, you have:
this.name = name;
and
this.price = price;
After the above two lines of code are executed, the property accessors automatically assign the private variables ("name" and "price") with the intended values.
So how are the lines:
this.name = name;
and
this.price = price;
able to call the public accessors, named "Name" and "Price"?
I have only seen when a public accessor is explicitly called such as:
saleProduct.Name = "Kitchen Garbage";
I don't understand how:
this.name = name;
and
this.price = price;
can access a private variable directly. I thought the whole point of property accessors was that you had to go via the property name in order to access the private variables such as:
saleProduct.Name = "Kitchen Garbage";
Can you help and explain how
this.name = name;
and
this.price = price;
is able to access the public properties? Even the name of the properties ie "Name" and "Price" are changed to "Kitchen Garbage" and "49.99" respectively when the above two lines of code are executed.
Also, how does
this.name = name;
and
this.price = price;
know which public accessor to call?
I have searched everywhere for an explanation but no luck.
Thank you.
The private members name and price are accessible in all non-static methods within the class Product. Since the constructor for Product is part of the class, the members are accessible there as well.
Your constructor is not using the public properties Name and Price. They retrieve their values from the corresponding private members.
this.name refers to private string name;. It's private, so only code inside the class can refer to it.
The this. prefix is only required because otherwise the code would be ambiguous, since there's a parameter called name as well.
The public accessor public string Name does not have any storage of its own. It passes through to the private field name.
The code this.name = name; does not touch the property Name - it's the other way around.
When you do this.name = name;, you are setting the value of the private field called name.
Whenever you access the public property Name, you are indirectly accessing that same field (name).
Look at the definition of the property:
get { return name; }
Note that here, name refers to the same field as this.name. You could change it to this.name and there'd be no effect. It's just not required here, since there's no ambiguity.
this.name = name;
and
this.price = price;
are used in the Constructor for the Product class. Private members are accessible from the Constructor (as well as from any non-static method on the class).
Basically, when you 'new' an object, the memory structure of the object is allocated, and then the constructor is called to allow for any initialization of that object. Making the name and price member variables private just means that you can only access them from inside the class members themselves, of which the constructor is.
The public properties Name and Price, as implemented here, are just wrappers around those private name and price variables, and allow you to do other things when setting or fetching (imagine wanting to count the number of times a value is referenced: you could increment some counter in the get{} of a public property).
in your constructor you are not setting the values via the public setter, you're setting the private backing field directly.
FYI I believe it is generally considered best practice to name class level items with an Upper letter (or underscore sometimes in the case of members/backing fields?), and function level variables and parameters with a lower letter. (Don't quote me on this paragraph :P)
so to set the field via it's setter just do:
public class Foo
{
private string _bar;
public string Bar
{
set
{
this._bar = value;
}
get
{
return _bar;
}
}
public Foo(string bar)
{
this.Bar = bar;
}
}
vs.
public Foo(string bar)
{
this._bar = bar
}
The above is equivalent to what you're doing in your code. Note with your current implementation it doesn't really make a difference, since you have no additional logic in your setter. If you did however, in your implementation you would miss out on that additional logic.
note i changed the variables around a bit to make it more obvious what's being done.
to demonstrate that point consider this:
public class Foo
private string _bar;
public string Bar
{
set
{
this._bar = value + " blah blah";
}
get
{
return _bar;
}
}
public Foo()
{
this.Bar = "test";
Console.WriteLine(Bar); // outputs "test blah blah"
this._bar = "test";
Console.WriteLine(Bar); // outputs "test"
}
}
The lower cased name and price are private 'backing' variables for the public Name and Price variables. They can only be accessed from within the class itself. The reason for using this.price is because the method is taking a param called 'price' so you need to specify that you're setting the classes field and not assigning to the local variable. You'll often see this in constructors, personally I would choose to name the arguments something different than the fields in my class and then it wouldn't be necessary.
I created a structure which contains several fields.
In that structure I have a property which calls a method which then creates a string out of those number for logging purposes.
When I use the property in the structure I get different decimal points Vs when I directly call the actual method which creates the log-string!
Suppose I have 9990M, if I use the structure it is 9990.0000 and when I call the method directly it prints 9990.00
This is my Method :
private static string CreateLog(
long userId, decimal amount,
long transactionID, decimal totalCash)
{
Values = string.Format("{0}{1}{2}{3}",
amount,
userId,
transactionId,
totalCash);
return Values;
}
And my structure looks like this:
public struct AccountStruct
{
public long USER_ID;
public decimal AMOUNT;
public long TRANSACTION_ID;
public decimal CURRENT_CASH;
string ValuesToBeLoged
{
get
{
return CreateLog(this);
}
}
}
And CreateLog looks like this (calls the former method)
private static string CreateLog(AccountStruct accinfo)
{
return CreateLog( accinfo.USER_ID,
accinfo.AMOUNT,
accinfo.TRANSACTION_ID,
accinfo.CURRENT_CASH);
}
Why is it like this ? whats the problem here?
Probably some sort of internal normalization is going on. If you care about such matters, you need to specify how many decimal places you want in the ToString or String.Format method.
Look up Decimal.ToString(String) for your options. Usually I use the "Nx" where x is the number of decimal places.
This is probably a simple thing to fix. I'm a university student and we just started polymorphism, so the concept is still puzzling to me.
abstract class IncreaseTransaction
{
private string _Description;
private decimal _Amount;
protected IncreaseTransaction(string description, decimal amount)
{
_Description = description;
_Amount = amount;
}
}
class Deposit : IncreaseTransaction
{
public Deposit(string description, decimal amount) : base("Deposit", amount)
{
}
}
static void Main(string[] args)
{
Customer fred = new Customer("Fred");
SavingsAccount fredSavings = new SavingsAccount();
fredSavings.AddTransaction(new Deposit(500.00M));
}
When a new deposit is instantiated, I want the literal string "Deposit" to be used as the description for the transaction. However, I'm getting an error stating 'SampleNamespace.Deposit does not contain a constructor that takes one argument'. So, the string is not being inherited, and I am unsure how to fix this. I would greatly appreciate any help!
Your constructor for Deposit takes two parameters:
public Deposit(string description, decimal amount) : base("Deposit", amount)
Since you're setting "Deposit" in the call to base(), you don't need 'string description' in that constructor. It should look like:
public Deposit(decimal amount) : base("Deposit", amount)
The following line should no longer throw an error:
fredSavings.AddTransaction(new Deposit(500.00M));
Additional Explanation: Constructors are not inherited like members or properties, but are unique to both the child and parent. The child (Deposit) has to invoke the base class's (IncreaseTransaction) constructor, but it does not need to require the same parameters in its own constructor.
Here is an old (but good) discussion of why this is the case: Why are constructors not inherited?
Here I have to write out a file which records are Pipe Separated, using FileHelpers and C#. Great part of fields have variable length (so, my records would be [DelimitedRecord("|")] ). But some fields must have fixed length (they must have paddings, specific format and so on).
I've googled a bunch with no goal on how to accomplish that.
Example:
[DelimitedRecord("|")]
public class Customer
{
public int CustId; //variable length
public string Name; //variable length
public decimal Balance; //variable length
[FieldConverter(ConverterKind.Date, "dd-MM-yyyy")]
public DateTime AddedDate;
public int Code; // this one must have 10 characters with "zero-fill", like
// 153 must look like 0000000153
}
How do I accomplish that? Do I have to use a Converter approach and write my own converter for this?
Thank you in advance.
For anyone who comes across this question in the future, here is some working code to solve this problem.
This class is a converter which the FileHelper engine will use to convert the integer to a string, padded with 0s up to the size specified in the constructor.
public class PaddedIntConverter:ConverterBase
{
private int _size;
public PaddedIntConverter(int size)
{
_size = size;
}
public override object StringToField(string from)
{
return int.Parse(from);
}
public override string FieldToString(object from)
{
return from.ToString().PadLeft(_size,'0');
}
}
The converter can then be applied to your class like this:
[FixedLengthRecord(FixedMode.ExactLength)]
public class MyClass{
[FieldFixedLength(7)]
[FieldConverter(typeof(PaddedIntConverter), 7)]
public int RecordCount;
}
FileHelpers has an attribute [FieldFixedLength(xxx)], I believe this should get you what you are looking for (http://filehelpers.sourceforge.net/attributes.html).
As mentioned by #TYY, I wrote my own "multiuse" converter, just like this:
public StringNumberCharConverter(
string Size,
string PaddingChar,
string PaddingType,
string RemoveSpecialChars)
{
//implementation here
}
Since FileHelpers converters accept string args only, I had to parse everything on proper objects inside the Converter constructor.
For the parameters, I've converted "Size" to an "integer", PaddingChar onto a "char", PaddingType onto a custom padding type enum (i.e: Padding.LEFT or Padding.RIGHT, so if a "left" is comming from parameters, I should use String.PadLeft() and so on), and the "RemoveSpecialChars" parameter were converted onto a boolean (flag to check if the converter should remove special characters or not.)
Since I need Object-to-File conversion, all the conversion logic is inside "FieldToString" method implementation of ConverterBase abstract method.