Change return program I did an application that returns you quarters, dimes, nickels and pennies after you give the cost of the product and the money you gave. Can this be done any better? This seems like kind of messed up, and it got some repeated code parts.

Console.Write("Cost of the product -&gt; ");
decimal costProduct = decimal.Parse(Console.ReadLine());

Console.Write("Money given -&gt; ");
decimal moneyGiven = decimal.Parse(Console.ReadLine());

decimal change = moneyGiven - costProduct;

decimal quarters = 0, dimes = 0, nickels = 0, pennies = 0;

while(change &gt;= 0.25m)
{
    quarters = Math.Truncate((change / 0.25m));
    change = change % 0.25m;
}

while(change &gt;= 0.10m)
{
    dimes = Math.Truncate((change / 0.10m));
    change = change % 0.10m;
}

while (change &gt;= 0.05m)
{
    nickels = Math.Truncate((change / 0.05m));
    change = change % 0.05m;
}

while (change &gt;= 0.01m)
{
    pennies = Math.Truncate((change / 0.01m));
    change = change % 0.01m;
}

Console.WriteLine("{0} quarters, {1} dimes, {2} nickels, {3} pennies", quarters,
    dimes, nickels, pennies);
Your code and both other answers are good. However, I see a gap in the assumption here. 


What if the list of available coins changes? This could be culture related (e.g. the Euro uses a €0.20 coin instead of the dollar's $0.25).
A similar issue could be encountered if you start factoring in the availability of change in your register (you can't give three quarters if you only have two)


To be fair, the second bullet point is not part of your current program. But if we solve the first bullet point, we have pretty much solved the second bullet point too (it requires minimal extra effort).  

I'm not going to implement the second bullet point, but adding this feature should be relatively easy in my reworked example.



So far, the coin values (and the coin types) have been hard-coded:

Your code:

while(change &gt;= 0.25m)


Danny's code:

decimal quarters = GetNumberOfCoins(ref change, 0.25m); 


Denis' code:

private const decimal _quarterValue = 0.25m;


All of them share the same traits: coin values are hardcoded, and so is the list of available coins.

Even though the values themselves are easily changed, changing the available coins (e.g. quarters are decommissioned, or a new coin value is created) creates a bigger workload, because you have to change the calls.

Realistically, the available coins don't change all that often (it would be insanity to try and change this on a federal level).
However, as I mentioned before, if your program needs to be able to handle both Euros and US dollars, then the available coins does change.

So let's improve this.

public class CoinType
{
    public decimal Value { get; set; } //e.g. 0.25
    public string Name { get; set; }   //e.g. "quarter"
}


Note that you can add other properties here:


char CurrencySymbol = '$'
int AmountOfCoinsAvailable = 100


But for the sake of simplicity, we'll only use the value and a name for printing.



Both you and the answerers have already identified that a generalized method should be created to check coin values. I'll not elaborate on the same, because it would just repeat the other answers.

Let's assume the following method exists:

private int CalculateMaxCoins(CoinType coin, decimal remainingAmount);


The return value is the amount of coins that you can use. E.g. 0.80 can fit 3 quarters, so 3 is the return value.



Now, we need to create a list of coins. Note that I'm making it a list instead of a bunch of separate properties, so that the list of available coins can easily be changed.

List&lt;CoinType&gt; availableCoins_USD = new List&lt;CoinType&gt;()
{
    new CoinType() { Value = 0.25m, Name = "quarter" },
    new CoinType() { Value = 0.10m, Name = "dime" },
    new CoinType() { Value = 0.05m, Name = "nickel" },
    new CoinType() { Value = 0.01m, Name = "penny" }
};


This allow us to easily change it to EUR:

List&lt;CoinType&gt; availableCoins_EUR = new List&lt;CoinType&gt;()
{
    new CoinType() { Value = 2, Name = "€2" },
    new CoinType() { Value = 1, Name = "€1" },
    new CoinType() { Value = 0.5m, Name = "50 cent" },
    new CoinType() { Value = 0.2m, Name = "20 cent" },
    new CoinType() { Value = 0.10m, Name = "10 cent" },
    new CoinType() { Value = 0.05m, Name = "5 cent" },
    new CoinType() { Value = 0.02m, Name = "2 cent" },
    new CoinType() { Value = 0.01m, Name = "1 cent" }
};


All the subsequent code will work regardless of the list of coins (so long as the list is comprehensive). So let's assume we've encapsulated this is a method:

private List&lt;CoinType&gt; GetCoinsForLocalCurrency();




We've defined how to get the coins, we've assumed that the calculation (of how many coins of a given type should be used already exists) (cfr the other answers)

All that remains is the logic inbetween these two:

private static void PrintListOfChange(decimal totalChange)
{
    //Get the coins and order them by value (descending)
    var coinTypes = GetCoinsForLocalCurrency()
                    .OrderByDescending(x =&gt; x.Value)
                    .ToList();

    //This is where we construct our result
    Dictionary&lt;CoinType, int&gt; neededChange = new Dictionary&lt;CoinType, int&gt;();

    //Placeholder value for calculations
    decimal remainingChange = totalChange;

    foreach(var coinType in coinTypes)
    {
        int coinAmount = CalculateMaxCoins(coinType, remainingChange);

        //Do nothing if the result was 0
        if(coinAmount &gt; 0)
        {
            //Add the results
            neededChange.Add(coinType, coinAmount);

            //See how much money is left to calculate
            remainingChange = remainingChange - (coinAmount * coinType.Value);

            //Minor performance gain:
            //  Stop processing if there is no money left to calculate.
            if (remainingChange == 0) break;
        }
    }

    //All that's left to do is print the values.

    string summaryOfChange = String.Join(
                                    " , ",
                                    neededChange.Select(x =&gt; $"{x.Key.Name} x{x.Value}") //e.g. "quarter x3"
                                );

    string fullmessage = $"{totalChange} in change equals: {summaryOfChange}";

    Console.WriteLine(fullmessage);
}


Ignoring the availability of a specific coin type, I think this is the most generalized approach. It requires a method to get the correct list of coins, but it works for any comprehensive list of coins that you provide.



I kept it a brief for the sake of example. There are extra features you could add:

1. What if the full total wasn't calculated in change? 

e.g. you were trying to find change for $1.06 but you have no pennies in your list. 

After the foreach, you can do:

if(remainingChange &gt; 0)
{
    Console.WriteLine($"{remainingChange} cannot be given in change!");
}


2. There are no currency symbols.

This likely ties into how you define the "local" currency. It's nothing but an extra character to prepend to all values when printing the list.

3. There is no support for plural nouns.

E.g. if you want to be able to print things like 3 quarters (plural) but also 1 quarter (singular).

You would have to define two separate Name properties for a CoinType:

public string Name_Singular { get; set; }   
public string Name_Plural { get; set; }


You might be tempted to add an "s" instead, but this falls apart in some cases:


Penny / Pennies
Most foreign currencies do not have a "given name" that is easily pluralized by adding an "s". Note the names I gave to the Euro coins, we lack a real name for the coin and simply list its value instead.