Assign values to arrays on structs using a comfortable code

Go To StackoverFlow.com

1

The idea is simple. Make a struct for "Departments" of a store, give it a variable for naming (a string called "Department"), and a array to save all buys done in that department.

Now, I want that every time that I'm gonna save a buy on a specific Department, it auto-applies a discount based on department's name and buy amount.

Now, the example class:

class Program
{
    struct Departments
    {
        public string Department;
        private double[] _buys;

        public double[] Buys
        {
            get { return _buys; }
            set
            {
                if (value > 100)
                {
                    if (Department == "CLOTH")
                    _buys = value * .95;
                    if (Department == "FOOD")
                    _buys = value * .90;
                    if (Department == "OTHER")
                    _buys = value * .97;
                }
                _buys = value;
            }
        }
    }

    static void Main()
    {
        var departments = new Departments[3];
        departments[0].Department = "CLOTH";
        departments[1].Department = "FOOD";
        departments[2].Department = "OTHER";
        departments[0].Buys = new double[5];
        departments[0].Buys[0] = 105;
    }
}

Note the line departments[0].Buys[0] = 105, that's the way that I want to save bought things, "Code-Simple"...

Now, note the property Buys of the struct, it's an "Array Property". Then, when I use the value > 100 condition it gives an obvious error, can't cast from double to double[].

The question... how can I write a right condition for value > 100, what else must be put on the stuct to achieve this?

I've tried with "Indexers", but as long as I've tried I can't make it take assignemts via departments[0].Buys[0] = 105 in the right way.

Please note that I wanna keep this schema, specially for the facility of simply say departments[0].Buys[0] = 105 to asing buyings

EDIT:

The previous struct "Departments" is done for example-purposes only. I won't answers about making it by another way to have right "Departments", I want an answer of how to make the set parameter work on individual elements of arrays

2012-04-05 02:42
by mishamosher
You don't want Departments to be a struct. It's not a value, don't treat it like one. And your setter is hosed. It's setting an array, not individual elements of one. Rethink your approach - Anthony Pegram 2012-04-05 02:44
@AnthonyPegram "It's setting an array, not individual elements of one." That same! Thanks for those words, hard to find those words xD. So, what can I do to make the setting thing to set individual elements of an array? Discard the Departments like something different to structs, at the end I want a answer on how to make set to work on idividual elements of array - mishamosher 2012-04-05 02:49
I'm working on change the focus of the question, because the real question isn't to make a right "Departments", the real question is to use set on individual elements of arrays - mishamosher 2012-04-05 02:51


2

One more potential solution is to make another class for the _buys array:

class Buys
{
    private double[] _buys;

    public Buys (int capacity)
    {
        _buys = new double[capacity];
    }

    public double this[int index]
    {
        get { return _buys; }
        set 
        {
            if (value > 100)
            {
                if (Department == "CLOTH")
                    value = value * .95;
                if (Department == "FOOD")
                    value = value * .90;
                if (Department == "OTHER")
                    value = value * .97;
            }
            _buys = value;
        }
    }
}

struct Departments
{
    public string Department;
    public Buys Buys;
}

static void Main()
{
    var departments = new Departments[3];
    departments[0].Department = "CLOTH";
    departments[1].Department = "FOOD";
    departments[2].Department = "OTHER";
    departments[0].Buys = new Buys(5);
    departments[0].Buys[0] = 105;
}
2012-04-05 03:21
by Andrew Cooper
This is the thing that I wanted to! Thanks a lot! Why teachers are so /#%$" with coding restrictions? And just for reference, I'm repeating here that "Bottom line is there's no way to make a setter for an element of an array - mishamosher 2012-04-05 03:27
@mishamosher because this design will burn whoever has to maintain the code - Yaur 2012-04-05 03:35
@Yaur I know... but I'm the only mantainer :P. It's not a real-life app, it's a simple homework that gave me doubts about sets and elements of arrays, and that's the core of the question that has been already answered by Andrew Coope - mishamosher 2012-04-05 03:42
@Andrew Cooper Until now I've realized that Department can't be accesed on Buys class. I changed the thing and applied inheritance, so, now I'm using classes and not structs - mishamosher 2012-04-05 04:01


1

You'd be better off using a List<double> to record the purchases. That way the list can grow dynamically. You can also use indexes to get the list elements.

You can simplify the discount code using a dictionary.

For this data you'd also be better off using a class, rather than a struct. Structs are generally better used for immutable values. Make the class represent a single department and store the appropriate discount in it.

So something like this:

class Program
{
    class Department
    {
        public string Name;
        public double Discount;

        private List<double> _buys = new List<double>();

        public List<double> Buys
        {
            get { return _buys; }
        }

        public void AddBuy(double value)
        {
            _buys.Add(value > 100 ? value * discount : value);
        }
    }

    static void Main()
    {
        var departments = new List<Department>();
        departments.Add(new Department { Name = "CLOTH", Discount = 0.95 });
        departments.Add(new Department { Name = "FOOD", Discount = 0.90 });
        departments.Add(new Department { Name = "OTHER", Discount = 0.97 });
        departments[0].AddBuy(105);

        Console.WriteLine(departments[0].Buys[0]);
    }
}

There are many other ways I'd improve this design, but this should get you going.

2012-04-05 03:03
by Andrew Cooper
Now suppose the following, I know that I'm just complicating things, but I've also some restrictions on the "Final App". Discard making Lists, Stacks, etc... arrays as much if needed. Also, discard discount being assignable, it's fixed and I won't to pass it as parameter. Having all this, the only solution I think is to make a special method that takes the buying amount and the index position and then do all the "magic work". With set thing isn't there a way, can't I make it point to individual elements of arrays and use it by the Property[index] way - mishamosher 2012-04-05 03:10
See my other answers for other options. Bottom line is there's no way to make a setter for an element of an array. You can wrap the array in another class and use an indexer, though. One of my other answers shows this technique - Andrew Cooper 2012-04-05 03:23


1

you could do something like this

public class Departments
{
    public string Department;
    public MyList buys;
    public Departments()
    {
        buys = new MyList(this, 5);
    }
}
public class MyList
{
    private double[] backingList;
    private Departments owner;
    public MyList(Departments owner, int size)
    {
        this.owner = owner;
        backingList = new T[size];
    }

    public double this[int index]
    {
        get{ return backingList[index]; }
        set { backingList[index] = discountFor(owner.Department) * value; }
    }

    private float discountFor(string department)
    {
        switch(department)
        {
        case "department1":
            return 0.5f;
        //...
        default:
             return 1.0f;
        }
    }

}

However you are not maintaining good separation of concerns by putting the discount into the setter its self. Better code would look something like

departments[0].Buys[0] = DiscountFor("department1") * 105;
2012-04-05 03:31
by Yaur
Liked more the way that it's done in Andrew Cooper's answer, simpler and I can apply nesting preserving a readable code (may be not well designed, but understable). Anyway, this is a solution, and thanks for i - mishamosher 2012-04-05 03:37


0

By your error you can do something like this.

struct Departments
    {
        public string Department;
        private double[] _buys;
        public double[] Buys
        {
            get { return _buys; }
            set
            {
                for (int i = 0; i < value.Length; i++)
                {
                    if (value[i] > 100)
                    {
                        if (Department == "CLOTH")
                            _buys[i] = value[i] * .95; if (Department == "FOOD")
                            _buys[i] = value[i] * .90; if (Department == "OTHER")
                            _buys[i] = value[i] * .97;
                    }
                }
                _buys = value;
            }
        }
    }
2012-04-05 03:05
by Vetrivel mp
Ok. Now, because the for loop it will retouch all the _buys stored previusly... a way of make this avoiding that - mishamosher 2012-04-05 03:12


0

You could create a method to do the setting like this:

        public double[] Buys { get; set; }

        public void SetBuy(int index, double value)
        {
           if (value > 100)
           {
              if (Department == "CLOTH")
               value = value * .95;
              if (Department == "FOOD")
               value = value * .90;
              if (Department == "OTHER")
               value = value * .97;
           }
           _buys[index] = value;
        }
2012-04-05 03:11
by Andrew Cooper
Already put this as a comment on your prevoius answer ;). Discarding this probability, is there a way with the set thing? Hope there is.. - mishamosher 2012-04-05 03:14


0

Structs which contain mutable references to mutable items are generally a bad idea, since such structures end up exhibiting a weird combination of value and reference semantics. For example, what should be the effect of:

  Departments dep1,dep2;
  ...
  dep1 = dep2;
  dep1.Department = "CLOTH";
  dep1.Buys[5] = 123;

It's hardly obvious that such a statement will or should affect dep2.Buys[5]. If a given structure's Buys field/property would always refer to the same array, such semantics might be tolerable, but what happens if the array needs to be resized?

2012-04-07 21:17
by supercat
Thanks for the info buddy, but, in this particular and singular case, it's a homework that hasn't many needs (however, it has restrictions :S). Teachers kill the student's smartness and ingenious with this exercises, and I'm really thankfull with all this answers because they open my mind... widely. Again, thank - mishamosher 2012-04-08 03:16
Ads