views:

46

answers:

4

Im sure this is simple but I've looked at it too long and I need an answer soon. I am new to C#. If I put GetCommission() within the struct I get

error CS0188: The 'this' object cannot be used before all of its fields are assigned to

outside the struct

error CS0038: Cannot access a non-static member of outer type 'Ex5._3.CommissionForm' via nested type 'Ex5._3.CommissionForm.salespersonFigures'

How do I get this done? Caveat: part of the assignment was that the commission be calculated in a method. None of the struct tutorials I've found deal with assigning one member based on the value of another. It should be kosher as the calculations only use static data. Right?

// Declare class variables and constants
private const decimal WEEKLY_BASE_SALARY = 250m;
private const decimal WEEKLY_QUOTA = 1000m;
private const decimal COMMISSION_RATE = .15m;

public struct salespersonFigures
{
    // Fields
    private string salesperson;
    private decimal weeklySales;
    private decimal commission;
    private decimal pay;

    // Constructor
    public salespersonFigures(string name, decimal sales)
    {
        salesperson = name;
        weeklySales = sales;
        commission = GetCommission(sales);  // error occurs at this line
        pay = WEEKLY_BASE_SALARY + commission;
    }

    // Property

    public decimal Sales
    {
        get
        {
            return weeklySales;
        }
        set
        {
            weeklySales = value;
        }
    }

    public string Name
    {
        get
        {
            return salesperson;
        }
        set
        {
            salesperson = value;
        }
    }

    // Method

    public decimal GetCommission(decimal sales)
    {
        if (sales > WEEKLY_QUOTA)
            return sales * COMMISSION_RATE;
        else return 0m;
    }
}
+1  A: 

The constructor:

// Constructor
public salespersonFigures(string name, decimal sales)
{
    salesperson = name;
    weeklySales = sales;
    commission = GetCommission(sales);
    pay = WEEKLY_BASE_SALARY + commission;
}

Is being interpreted as:

// Constructor
public salespersonFigures(string name, decimal sales)
{
    this.salesperson = name;
    this.weeklySales = sales;
    this.commission = this.GetCommission(sales);
    this.pay = WEEKLY_BASE_SALARY + this.commission;
}

So, the problems you could be encountering could be resolved by doing two things:

// Constructor
public salespersonFigures(string name, decimal sales)
{
    salesperson = name;
    weeklySales = sales;
    var tempCommission = GetCommission(sales);
    commission = tempCommission
    pay = WEEKLY_BASE_SALARY + tempCommission;
}

And make the GetCommission method static

McKay
Thank you very much McKay. I forgot that when I moved GetCommission() outside the struct I had to tell it what object GetCommission() belonged to. It helped very much to see how my code was interpreted. I changed these lines in my program: /n var tempCommission = CommissionForm.GetCommission(sales); commission = tempCommission; /n
slomobile
That prompted intelisense to offer to create a stub method resulting in: internal static decimal GetCommission(decimal sales) { if (sales > WEEKLY_QUOTA) return sales * COMMISSION_RATE; else return 0m; throw new NotImplementedException(); } Could you explain why the method needs to be static? What is changed?
slomobile
Static members don't need to have an instance of the object to be used. But that also means they can't access members of an instance. C# has a condition: "The 'this' object cannot be used before all of its fields are assigned to" To protect you from using a struct before it's ready. Does that answer your questions?
McKay
A: 

Do you really need commision field?

private decimal commission;

You can delete it and have you method in a struct. And I think you don't need sales parameter in yout GetComission method.

Andrew Bezzub
Perhaps I should have named that method CalculateCommission() as what it is really doing is figuring out the commission based on the sales parameter passed to it. So the sales parameter is absolutely necessary as this method will also be used with data other than the struct as well. The fields I chose to include in the struct represent data I will use later in various ways. I want to perform the calculations now and store the results indefinitely rather than defer the processing till they are viewed, at which time some of the constants may have changed.
slomobile
You can use sales field already existing in your structure instead of parameter.
Andrew Bezzub
That would make the method unusable by another event handler on the form which allows salesman to see what their commission would be if they made a given level of sales. Also doesn't address my problem.
slomobile
A: 

Very simple workaround / hack:

public salespersonFigures(string name, decimal sales)
{
      salesperson = name;
      weeklySales = sales;
      // initialize pay and commission
      pay = 0m;
      commission = 0m;
      commission = GetCommission(sales);
      pay = WEEKLY_BASE SALARY + commission;
}

And you do not need the else part of the clause in getCommission, just do this:

public decimal GetCommission(decimal sales)
{
    if (sales > WEEKLY_QUOTA)
        return sales*COMMISSION_RATE;
    return 0m;
}

One more thing, why are you using decimal? You should probably use double's or float's instead, because more methods rely upon float's and doubles's and converting between can be costly

Richard J. Ross III
That doesn't really solve my problem. Thanks for the effort though.
slomobile
How does it not? EDIT: I fixed it...
Richard J. Ross III
I see that omitting the else also works, but does it result in a performance improvement? I feel that the else improves the readability of the code, however I will leave it out in future situations if it is an optimization. I am using decimal due to its exact nature and nicer format options when dealing with currency. Doing so is recommended by my instructor and textbook. I am conscious of its cost in memory, it wont need to be cast to other types. While your edited solution may work if the method is left inside the struct, I have chosen to leave it outside.
slomobile
No, it isn't a performance issue as far as I know, but it is an issue of style. If you are going to use the `else` clause, then have the `return 0m` on a new line, It will make it look better in my opinion... And decimal thing I didn't realize that you were using it ONLY for monetary things, as yes, decimals have greater precision when using arithmetic operations on them...
Richard J. Ross III
Decimals are better than doubles and floats because they provide better precision. Yes, some methods don't support them, but really only those that don't need the precision.
McKay
A: 

Why not just make GetCommission() into a property: Commission.

There is no need to store commission as a field, it should be a query against the SalespersonFigures object

CrapHands
As I mentioned in a previous comment, the commission needs to be stored because it represents the amount that will be paid at a given point in time. If at some future date the constant for WEEKLY_QUOTA, CMMISSION_RATE, or the pay period change, then all records of previously paid comissions will be lost.
slomobile