-1

I'm creating a donation application that reads the input in a textbox, converts it to a double. Then using the method operatingCost, it should take that converted double and divide it by 17% (operating fees). Currently in the method, I have the variable dontationBFees coming in and then being divided by 17 and creating a new variable afterFees. The problem I'm having is that I need to pass by ref in this project and I cant seem to access the afterFees variable. I need to get the ref afterFees and have it displayed to my afterFeesBox. Also I have this method inside my button on_click. Any help will be greatly appreciated. Below is my code:

   private Double donationBFees = 0;


    private void button1_Click(object sender, EventArgs e)
    {
        String donationBeforeFees;
        Double aFees;
        String totalDonationRaised;

        donationBeforeFees = donationBox.Text;
        donationBFees = System.Convert.ToDouble(donationBeforeFees);

        void operatingCost(ref double afterFees)
        {
            afterFees = (donationBFees / 17);
        }


        afterFeesBox.Text = operatingCost(ref afterFees);


    }
Jeff Ryan
  • 19
  • 4
  • 1
    How/where do you declare `afterFees`? – eye_am_groot Oct 18 '18 at 14:46
  • 4
    Side note: for monetary values, use `decimal`: https://stackoverflow.com/questions/1165761/decimal-vs-double-which-one-should-i-use-and-when – Broots Waymb Oct 18 '18 at 14:46
  • 3
    Refactor suggestion: put your `void operatingCost(ref double afterFees)` method outside of your click event method. Btw. it returns `void` - you cant assign it to a text property that way. I would do the following: change your method to `double operatingCost(double fees)` call it like `afterFees = operatingCost(donationBFees)` - no ref needed. Everything untested, please check if it is still your wanted output! – nilsK Oct 18 '18 at 14:47
  • 4
    _"I need to pass by ref in this project"_ - why is that? – Fildor Oct 18 '18 at 14:51
  • @Greg I declare afterFees in the method and its also created there. – Jeff Ryan Oct 18 '18 at 14:59
  • @Fildor The project calls for the us of pass by ref to be used. If I didn't need it, this would be a lot easier but I cant seem to get the pass by ref working. – Jeff Ryan Oct 18 '18 at 15:00
  • @nilsK Thanks for the void tip. I was doing that originally but the project calls for the use of pass by ref so its needed. When I had it outside of my btnClick, I tired calling it using operatingCost(ref afterFees) and it wasnt working. – Jeff Ryan Oct 18 '18 at 15:05
  • What do you mean `divide by 17%`? Maybe it's `afterFees = afterFees - (afterFees * .17D);` in `operatingCost()` Then you can use a new variable: `double donationAfterFees = donationBFees; operatingCost(ref donationAfterFees); afterFeesBox.Text = donationAfterFees.ToString();`. The use of `ref` in this inline function is weird. Also, as already stated, when you are calculating currency, use decimal, not double (ever). – Jimi Oct 18 '18 at 15:07
  • That is really an odd convention for a c# project. But well, so be it. You need to declare a variable first, then pass it by ref, then use it. Side note: you may want to add some validation. Never trust user input. – Fildor Oct 18 '18 at 15:12
  • @Fildor Yes, I was thinking of adding a if statement to check if the user input is validate i.e. no strings. Thank you for the help – Jeff Ryan Oct 18 '18 at 15:15

3 Answers3

0

Calling byref changes the value that is passed into a function, so you need to pass in a variable that you don't mind being change.

In this example I've had two things called afterFees, so I renamed one to make it obvious that one is a parameter.

private Double donationBFees = 0;

void operatingCost(ref double afterFeesParam)
{
    afterFeesParam = (afterFeesParam / 17);
}

private void button1_Click(object sender, EventArgs e)
{
    String donationBeforeFees;
    Double aFees;
    String totalDonationRaised;

    donationBeforeFees = donationBox.Text;
    donationBFees = System.Convert.ToDouble(donationBeforeFees);

    double afterFees = donationBFees;
    operatingCost(ref afterFees);
    afterFeesBox.Text = afterFees;
}

You should tell your prof that this is not really a good use of a byref parameter. It might make more sense if the function deducted the operating cost:

void deductOperatingCost(ref double afterFeesParam)
{
    afterFeesParam = afterFeesParam - (afterFeesParam / 17);
}

That way you give it a value and it comes back slightly smaller.

Robin Bennett
  • 3,192
  • 1
  • 8
  • 18
  • 1
    Thank you very much Robin. This helped me out greatly. I kept the afterFeesParam in my code to not get confused with the other variables. I also changed to decimal as suggested by other and I also noticed I was calculating the percentage wrong so I fixed that. Thank you for all of the advise and help. – Jeff Ryan Oct 18 '18 at 16:45
0

A few (hopefully helpful) things:

void operatingCost(ref double afterFees)
{
    afterFees = (donationBFees / 17);
}

This means that you are passing in a reference to afterFees and, in the method, doing things to afterFees (this this case, assigning it to donationBFees / 17), and not returning anything. However, this line:

afterFeesBox.Text = operatingCost(ref afterFees);

means you are assigning Text to the result of that method, which doesn't work since it's return type is void.

You also never declare afterFees, except in that method (which doesn't work). I imagine you are getting an error "The name... does not exist in the current context." You need to declare this variable locally (and rename it to not conflict):

double partAfterFees = 0;
operatingCost(ref partAfterFees);

So a few things you could do:

1) return a type (you are currently using double but, as suggested in the comments, may want to use decimal). Then you could remove the ref if you want. You could then do something like:

double operatingCost(ref double afterFees)
{
    afterFees = (donationBFees / 17);
    return afterFees;
}
afterFeesBox.Text = operatingCost(ref partAfterFees).ToString();

But this seems odd, so I may just do (given what you've said):

double partAfterFees = 0;
operatingCost(ref partAfterFees);
afterFeesBox.Text = partAfterFees.ToString();

Note, there are "better" solutions involving refactoring and checking for valid input, etc. But I think this answers your questions.

eye_am_groot
  • 682
  • 6
  • 19
  • Thank you Greg, I changed a few things in my code. I noticed (with help) that my calculations for percentage where off. I fixed that by trial and error and now its working. I also changed to decimal instead of double as suggested. – Jeff Ryan Oct 18 '18 at 16:43
0

I moved the method out of the onClick, I changed the calculation for finding the percentage of the donation (user input). I also formatted the output to display only two places after the decimal and display a dollar sign. I still need to create error handlers to validate the user input but that shouldn't be an issue. I had issues with the pass by ref but I have a lot better understand how it works. Thank you everyone for the help!

private decimal donationBFees = 0;

    void deductOperatingCost(ref decimal afterFeesParam)
    {
        afterFeesParam = afterFeesParam - (afterFeesParam  / 100 * 17);
    }


    private void Button_Click(object sender, RoutedEventArgs e)
    {
        String donationBeforeFees;
        Decimal aFees;
        String totalDonationRaised;

        donationBeforeFees = donationBox.Text;
        donationBFees = System.Convert.ToDecimal(donationBeforeFees);


        decimal afterFees = donationBFees;
        deductOperatingCost(ref afterFees);
        afterFeesBox.Text = afterFees.ToString("$###, ##0.00");

    }
Jeff Ryan
  • 19
  • 4
  • Introducing donationBFees as class field is not the best idea, because it can lead to unwanted side-effects. A local declaration would absolutely be enough. – Fildor Oct 19 '18 at 07:59