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.
Related
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).
I have a method with the following signature:
bool DoSomething();
I want to change it to this:
bool DoSomething(IList<int> newIDs);
The boolean and the list of IDs are not related to each other. The new method contains an extra output that contains the list of new IDs. Is this bad practice? What is the right way to return multiple values in this situation?
You could also "wrap" all the return values inside an object:
public class Payload
{
public List<int> NewIDs { get; set; }
public bool Status { get; set; }
}
//Use Payload class
public Payload DoSomething(...){...}
I think it's important to understand what the semantics of the returned values are before deciding on a specific pattern. If you edit your question with details, I'll provide more insight as well.
Cheers
There is a common pattern called the TryParse pattern that is used extensively within the C# Base Class Library which is basically the same as your function signature.
For example: DateTime.TryParse
public static bool TryParse(
string s,
out DateTime result
)
I think it is fine to use this provided you include the 'out' keyword.
Edit:
Also give the function a name that makes it clear why it returns a null.
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.
i have create a class library (DLL) with many different methods. and the return different types of data(string string[] double double[]). Therefore i have created one class i called CustomDataType for all the methods containing different data types so each method in the Library can return object of the custom class and this way be able to return multiple data types I have done it like this:
public class CustomDataType
{
public double Value;
public string Timestamp;
public string Description;
public string Unit;
// special for GetparamterInfo
public string OpcItemUrl;
public string Source;
public double Gain;
public double Offset;
public string ParameterName;
public int ParameterID;
public double[] arrayOfValue;
public string[] arrayOfTimestamp;
//
public string[] arrayOfParameterName;
public string[] arrayOfUnit;
public string[] arrayOfDescription;
public int[] arrayOfParameterID;
public string[] arrayOfItemUrl;
public string[] arrayOfSource;
public string[] arrayOfModBusRegister;
public string[] arrayOfGain;
public string[] arrayOfOffset;
}
The Library contains methods like these:
public CustomDataType GetDeviceParameters(string deviceName)
{
......................
code
getDeviceParametersObj.arrayOfParameterName;
return getDeviceParametersObj;
}
public CustomDataType GetMaxMin(string parameterName, string period, string maxMin)
{
.....................................code
getMaxMingObj.Value = (double)reader["MaxMinValue"];
getMaxMingObj.Timestamp = reader["MeasurementDateTime"].ToString();
getMaxMingObj.Unit = reader["Unit"].ToString();
getMaxMingObj.Description = reader["Description"].ToString();
return getMaxMingObj;
}
public CustomDataType GetSelectedMaxMinData(string[] parameterName, string period, string mode)
{................................code
selectedMaxMinObj.arrayOfValue = MaxMinvalueList.ToArray();
selectedMaxMinObj.arrayOfTimestamp = MaxMintimeStampList.ToArray();
selectedMaxMinObj.arrayOfDescription = MaxMindescriptionList.ToArray();
selectedMaxMinObj.arrayOfUnit = MaxMinunitList.ToArray();
return selectedMaxMinObj;
}
As illustrated thi different methods returns different data types,and it works fine for me but when i import the DLL and want to use the methods Visual studio shwos all the data types in the CustomDataType class as suggestion for all the methods even though the return different data.This is illusrtated in the picture below. As we can see from the picture with the suggestion of all the different return data the user can get confused and choose wrong return data for some of the methods. So my question is how can i improve this. so Visual studio suggest just the belonging return data type for each method.
You're taking a fundamentally wrong approach.
Make each method's return type a type which includes the appropriate data. Some methods may have the same return type as each other; for other data types there may only be a single method which returns that type.
In some cases generics may help - for example, if you have different methods which return a "minimum and maximum value", sometimes long, sometimes int, sometimes float or whatever, then you could have a MinMax<T> type.
This should have given you the hint:
and the return different types of data
Given that the methods naturally "return different types of data" why would you give them all the same return type?
But putting everything into one data type is simply not the way forward. (It's also extremely inefficient, but that's a second order concern.)
Next step: get rid of those public fields, and use properties instead. You should consider whether it would make sense for some of your types to be immutable, and where you're currently exposing arrays, expose read-only collections instead.
if you really want to use the aproach you have I might sugest using dynamics
public dynamic GetDeviceParameters(string deviceName)
{
......................
code
getDeviceParametersObj.arrayOfParameterName;
return getDeviceParametersObj;
}
You are kind of working against the type system. I think your CustomDataType class will cause more problems than it will solve.
You should either create classes for each combination you will be using, or use out parameters to be able to return more than one value from a method.
There is no way to tell Visual Studio to ignore certain properties based on which method it was returned from.
Trying to decipher an appropriate OO design to implement. The basic scenario is that you have a PstnNumber which is essentially a 10 digit phone number that always starts with 0 (e.g. 0195550000). A rule has been introduced to allow auto-correcting of a number if the leading 0 is missing (e.g. 195550000).
START EDIT
I realised the original question may have been misunderstood (thankyou kindly to those whom have answered already), so I have edited to try and better explain the scenario.
END EDIT
I started playing with some preliminary concepts and then thought I would ask if there was a more appropriate way to go or do one of these suffice (on some level)?
Concept 1
public class PstnNumber
{
public virtual string Number { get; set; }
public PstnNumber() { }
public PstnNumber(string number)
{
this.Number = number;
}
}
public class AutoFormattedPstnNumber : PstnNumber
{
public override string Number
{
get { return base.Number; }
set { base.Number = value.PadLeft(10, '0'); }
}
public AutoFormattedPstnNumber() : base() { }
public AutoFormattedPstnNumber(string number)
{
this.Number = number;
}
}
Concept 2 (removed)
Concept 3
public class PstnNumber
{
public bool AutoCorrect { get; set; }
private string number;
public virtual string Number
{
get { return (this.AutoCorrect) ? this.number.PadLeft(10, '0') : this.number; }
set { this.number = value; }
}
public PstnNumber() : this(false) { }
public PstnNumber(bool autoCorrect)
{
this.AutoCorrect = autoCorrect;
}
public PstnNumber(string number) : this(false)
{
this.Number = number;
}
public PstnNumber(string number, bool autoCorrect) : this(autoCorrect)
{
this.Number = number;
}
}
I think Concept 1 may violate the Liskov Substitution rule because the subclass changes the behaviour of the Number property (happy to learn if I've misunderstood that).
Any alternative suggestions would be received happily.
do you have to do the autoformatting when the object is instantiated? If not,
what about:
public class PstnNumber
{
public virtual string Number { get; set; }
public PstnNumber() { }
public PstnNumber(string number) { this.Number = number; }
public AutoFormatNumber { get { return Numer.PadLeft(10, '0'); } }
}
avoid getter-setter-surprise
Avoid getters returning a different value than the one accepted by the setter. Imagine the following snippet:
if (input.Value != current.Number)
{
NumberChangedAgain = true;
current.Number = input.Value;
}
A simple solution would be to make PstnNumber immutable:
temp = PstnNumber.FromString(input.Value);
if (temp != current) { ... }
canonical format
If some data has different representations, there is a lot of advantage to storing it in a canonical representation, and move the format conversions to factory functions and getters / formatters. For example, you don't need to test comparison for short vs. long, long vs. short, short vs. short, long vs. long.
different aspects
Do you need the distinction between an "autoformatted" and a "normal" number, or is this merely a question of input and output - i.e.
does display format (short or long) depend on how the number was entered, or on where it is displayed?
is 0195550000 == 195550000 ?
I'd prefer to fold both classes into one if possible (i.e. when "entered with or without 0 can be forgotten"):
public class PstnNumber
{
private string m_number; // always in long format
public static PstnNumber(string s) { ... } // accepts short and long form
public string Number { get { return m_number; } }
public string AutoFormatted { { get { ... } }
}
Otherwise I'd go with Option 3, but always store the long format in m_number.
In Option 1 and Option 2, you aren't preserving the original number anyway, rendering the subclass worthless (except to know that it was autoformatted at some point, which doesn't seem like useful information). The alternative to make these Options more useful would be to format on Get instead of Set.
Option 3 is therefore the preferred pattern out of these three options, but I would also ask - why can't the PstnNumber also simply detect the number of digits, and autoformat accordingly?
If you follow the rules - there is one that says that "each routine (read class) should do only one thing and do it well".
According to that I would make PstnNumber just hold the number, and create some sort of factory that produces the right number.
Doing both in the same class means that you are weaving domain logic and representation. I prefer them separated.
I'd ask why your class name is so cryptic. "Number" is clear to me, and "P" suggests "phone", but what's the "stn" telling me? A few extra keystrokes would make this class more self-documenting.
I'd also ask about the logic of a default constructor that does not initialize the underlying data members to some value. I think a default constructor should have a sensible default value if possible.
I feel like option 1 is overkill. I don't think inheritance is making this model clearer or better. I don't see how it breaks Liskov substitution, which demands that you can use the subclass in any situation that calls for a base class. The methods map 1:1 as far as I can see. How is Liskov violated?
Option 2 says these are two separate classes with no relationship. That doesn't seem right to me.
All this work suggests that your problem will require that you use both classes. You'll have situations where the leading zero is NOT required and others where it is. Is that true? Or are you always going to require the leading zero?
I don't care for any of your options. I'd prefer an interface or a static factory or even modifying the class you have to anything you've suggested. It feels like a mere formatting issue. Do you store the number with the leading zero? If not, maybe it's just a view concern.
Do you have a really strong reason to have a setter and not have your members final? If not, that's probably a bigger problem than any other variation between the three.
So I'd go for a stateless #3 which means making the number final and gettng rid of the autoFormat variable.
For simplicity I'd just have a getNumberRaw and getNumberFormatted
Better yet, you could have getNumberRaw and getNumber(formatType) where formatType actually contains the code that formats the number since the format may change again in the future and combining formatting (view) with your phone number (model) isn't optimal.
(PS/EDIT): just the fact that a phone number can change is NOT a good reason to have a setter! Creating a new phone number object and replacing the old one will almost always work!
I am not familiar with c#, but I'd do this:
public class PstnNumber {
readonly string number;
public PstnNumber(string number) {
this.number = number;
}
public string getNumber() {
return number;
}
static public PstnNumber createNumber(string number) {
return new PstnNumber(number.PadLeft(10, '0'));
}
}
Of course if I knew how Properties work, I'd probably do it differently :)
I would go with a much simpler version, overriding the ToString method, or even, creating an ToString overload that receives the bool parameter indicating that the number should be formatted.