i created an extension method for decimal AsCurrency(this decimal amount)
when i build i will get an error
The call is ambiguous between the following methods or properties:
'CurrencyHelper.AsCurrency(decimal)' and
'CurrencyHelper.AsCurrency(decimal)'
whate hell? if i clear solution, it will build again. next time it will fail again.
Is the problem with decimal or has there gone something wrong with my solution?
Has anyone encountered same problem?
Edit
Extensions are in one assembly. CurrencyHelper has only one definition.
here's the code:
public static class CurrencyHelper
{
public static string AsCurrency(this decimal amount)
{
return ((decimal?) nr).AsCurrency();
}
public static string AsCurrency(this decimal? amount)
{
var cultureInfo = ...
return (nr ?? 0).ToString("c2", cultureInfo);
}
}
The idea is to format decimal value with needed cultureinfo and if amount is null, 0 is still provided
Ok. problem solved
seems like someone in our team added reference to project itself. Thanks for the tip, Hans
Related
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.
I have a basic class with this method including
public class Account
{
//MEMBERS
private int acctNo;
protected double balance;
public double deposit;
// CONSTRUCTORS
public Account() //member intitilization
{
acctNo = 54534190;
balance = 7500;
deposit= 1500;
}
//PROPERTIES
public int AcctNo
{
get {return acctNo; }
set {acctNo = value; }
}
public double Balance
{
get { return balance; }
set { balance = value; }
}
public double Deposit
{
get {return deposit; }
set {deposit = value; }
}
public virtual double getDeposit (double amount)
{
double transactionAmt=0.00;
if (amount>0)
{
balance+=amount;
transactionAmt= amount;
}
return transactionAmt;
}
Now in my actual program I am trying to output this method. What would my writeline look like?
I tried to write this:
static void Main(string[] args)
{
Console.WriteLine("CREATING ACCOUNT");
Account myAcctDefault = new Account();
DumpContents(myAcctDefault);
Pause();
}
static void DumpContents(Account account)
{
Console.WriteLine(" output {0}", account.getDeposit());
}
I am getting an error saying:
no overload for method 'getDeposit' takes 0 arguments.
What am I doing wrong, am I trying to output this method incorrect?
Any help, insight or suggestions would be extremely helpful.
I am new to c# as I'm sure you can tell. What is the proper process to output a method in this context?
I am getting an error saying "no overload for method 'getDeposit' takes 0 arguments". What am I doing wrong
Exactly what it says. Here's your method call:
Console.WriteLine(" output {0}", account.getDeposit());
... and here's the method declaration:
public virtual double getDeposit (double amount)
Note how the method declares a parameter - but you're not providing an argument. Either you need to get rid of the parameter, or you need to add an argument to the method call. Or you need to change to using a different method - one which doesn't change the balance of the account. (It seems unlikely that you want to do that in this case.) Perhaps you should add a Balance property:
// Please note that this should probably be decimal - see below
public double Balance { get { return balance; } }
Then call it with:
Console.WriteLine(" output {0}", account.Balance);
Additionally:
For financial quantities, it's generally better to use decimal than double. Read my articles on decimal floating point and binary floating point for more information.
Your getDeposit method doesn't follow .NET naming conventions, where (at least public) methods are named in PascalCase, with a leading capital letter
Your getDeposit method is oddly named as it isn't "getting" a deposit - it's making a deposit (and returning the balance)
Your getDeposit method always returns the value passed into it, unless it's negative. That seems odd to me - if it's going to return anything, shouldn't it return the balance?
Your getDeposit method silently ignores negative deposits. I'd expect this to throw an error, as trying to make a negative deposit indicates a programming error IMO.
Your getDeposit method takes one argument that you are not passing to it. Depends what you want to achieve either pass a value to method:
static void DumpContents(Account account)
{
double deposit = 1000;
Console.WriteLine(" output {0}", account.getDeposit(deposit));
}
or remove this argumentparameter from the method signature.
//You have to pass a double value into the method, because there is only one method
//and wants a double paramater:
//this is what you created:
public double getDeposit(double amount) // <-
{
double transactionAmt = 0.00;
if (amount > 0)
{
balance += amount;
transactionAmt = amount;
}
return transactionAmt;
}
//This how you should call it:
static void DumpContents(Account account)
{
Console.WriteLine(" output {0}", account.getDeposit(34.90)); //<-
}
Im trying to use this method called GetDouble but i keep getting the error "no overload for method 'GetDouble' takes 1 arguments" and i have no idea how to fix it.
public static bool GetDouble(string StringToConvert, out double dblOutValue)
{
return double.TryParse(StringToConvert, out dblOutValue);
}
im calling it from this method
private bool ReadAndValidatePrice(out double price)
{
price = 0.0;
if (!InputUtility.GetDouble(txtPrice.Text))
{
}
}
Any help trying to fix it is appriciated, thanks.
As the error is trying to tell you, GetDouble() takes two arguments.
The second argument is an out parameter, meaning that it will set the variable you pass to it as a result.
When calling it, you must pass a variable with the out keyword.
You have a few issues here. The first is your GetDouble method. What are you trying to do? If you are trying to just get the double (as the name implies) then it should be more like
public static double GetDouble(string StringToConvert)
{
double dblOutValue;
double.TryParse(StringToConvert, out dblOutValue);
return dblOutValue;
}
Then look at your ReadandValidatePrice method. With the above change it should be more like:
private bool ReadAndValidatePrice(out double price)
{
price = InputUtility.GetDouble(txtPrice.Text)
//not sure if the IF statement is needed anymore so it is omitted
}
How is that? Where my assumptions completely wrong?
You miss one parameter ,GetDouble() takes two parameters. But you have pass one parameter, So you got that error . Now try below method instead of your method .
private bool ReadAndValidatePrice(out double price)
{
price = 0.0;
if (!InputUtility.GetDouble(txtPrice.Text, out price ))
{
}
}
Your method should look like follow, because your GetDouble() method defines two parameter:
private bool ReadAndValidatePrice(out double price)
{
price = 0.0;
if (!InputUtility.GetDouble(txtPrice.Text, out price))
{
}
}
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.
I find the following bug occurring far too often in my code and wondered if anyone knows some good strategies to avoid it.
Imagine a class like this:
public class Quote
{
public decimal InterestRate { get; set; }
}
At some point I create a string that utilises the interest rate, like this:
public string PrintQuote(Quote quote)
{
return "The interest rate is " + quote.InterestRate;
}
Now imagine at a later date I refactored the InterestRate property from a decimal to its own class:
public class Quote
{
public InterestRate InterestRate { get; set; }
}
... but say that I forgot to override the ToString method in the InterestRate class. Unless I carefully looked for every usage of the InterestRate property I would probably never notice that at some point it is being converted to a string. The compiler would certainly not pick this up. My only chance of saviour is through an integration test.
The next time I call my PrintQuote method, I would get a string like this:
"The interest rate is Business.Finance.InterestRate".
Ouch. How can this be avoided?
By creating an override of ToString in the IntrestRate class.
The way to prevent this kind of problem is to have a unit test for absolutely all your class members, which therefore includes your PrintQuote(Quote quote) method:
[TestMethod]
public void PrintQuoteTest()
{
quote = new Quote();
quote.InterestRate = 0.05M;
Assert.AreEqual(
"The interest rate is 0.05",
PrintQuote(quote));
}
In this case, unless you defined a implicit conversion between your new InterestRate class and System.Decimal, this unit test would actually no longer compile. But that would definitely be a signal! And if you did define an implicit conversion between your InterestRate class and System.Decimal, but forgot to override the ToString method, then this unit test would compile, but would (correctly) fail at the Assert.AreEqual() line.
The need for having a unit test for absolutely every class member cannot be overstated.
Creating an override of ToString is just one of those things you do for most, if not all, classes. Certainly for all "value" classes.
Note that ReSharper will generate a lot of the boilerplate code for you. From:
public class Class1
{
public string Name { get; set; }
public int Id { get; set; }
}
The result of running Generate Equality Members, Generate Formatting Members and Generate Constructor is:
public class Class1 : IEquatable<Class1>
{
public Class1(string name, int id)
{
Name = name;
Id = id;
}
public bool Equals(Class1 other)
{
if (ReferenceEquals(null, other))
{
return false;
}
if (ReferenceEquals(this, other))
{
return true;
}
return Equals(other.Name, Name) && other.Id == Id;
}
public override string ToString()
{
return string.Format("Name: {0}, Id: {1}", Name, Id);
}
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj))
{
return false;
}
if (ReferenceEquals(this, obj))
{
return true;
}
if (obj.GetType() != typeof (Class1))
{
return false;
}
return Equals((Class1) obj);
}
public override int GetHashCode()
{
unchecked
{
return ((Name != null ? Name.GetHashCode() : 0)*397) ^ Id;
}
}
public static bool operator ==(Class1 left, Class1 right)
{
return Equals(left, right);
}
public static bool operator !=(Class1 left, Class1 right)
{
return !Equals(left, right);
}
public string Name { get; set; }
public int Id { get; set; }
}
Note there is one bug: it should have offered to create a default constructor. Even ReSharper can't be perfect.
Not to be a jerk but write a test case each time you create a class. It is a good habit to get into and avoids oversights for you and others participating in your project.
Well, as others have said, you just have to do it. But here are a couple of ideas to help yourself make sure you do it:
1) use a base object for all of your value classes that overrides toString and, say, throws an exception. This will help remind you to override it again.
2) create a custom rule for FXCop (free Microsoft static code analysis tool) to check for toString methods on certain types of classes. How to determine which types of classes should override toString is left as an exercise for the student. :)
In the case where ToString is called on something statically typed as an InterestRate, as in your example, or in certain related cases where an InterestRate is cast to Object and then immediately used as a parameter to something like string.Format, you could conceivably detect the problem with static analysis. You could search for a custom FxCop rule that approximates what you want, or write one of your own.
Note that it will always be possible to devise a sufficiently dynamic call pattern that it breaks your analysis, probably not even a very complicated one ;), but catching the lowest-hanging fruit should be easy enough.
That said, I agree with some of the other commenter that thorough testing is probably the best approach to this specific problem.
For a very different perspective, you could defer all ToString'ing to a separate concern of your application. StatePrinter (https://github.com/kbilsted/StatePrinter) is one such API where you can use the defaults or configure depending on types to print.
var car = new Car(new SteeringWheel(new FoamGrip("Plastic")));
car.Brand = "Toyota";
then print it
StatePrinter printer = new StatePrinter();
Console.WriteLine(printer.PrintObject(car));
and you get the following output
new Car() {
StereoAmplifiers = null
steeringWheel = new SteeringWheel()
{
Size = 3
Grip = new FoamGrip()
{
Material = ""Plastic""
}
Weight = 525
}
Brand = ""Toyota"" }
and with the IValueConverter abstraction you can define how types are printer, and with the FieldHarvester you can define which fields are to be included in the string.
Frankly, the answer to your question is that your initial design was flawed. First, you exposed a property as a primitive type. Some believe this is wrong. After all, your code allows this ...
var double = quote.InterestRate * quote.InterestRate;
The problem with that is, what is the unit of the result? Interest^2? The second problem with your design is that you rely on an implicit ToString() conversion. Problems with relying on implicit conversion are more well known in C++ (for example), but as you point out, can bite you in C# as well. Perhaps if your code originally had ...
return "The interest rate is " + quote.InterestRate.ToString();
... you would have noticed it in the refactor. Bottom line is if you have design issues in your original design, they might be caught in refactor and the might not. Best bet is to not do them in the first place.