Using getter/setter for an array - c#

I'm trying to create a getter/setter for an array but I'm not sure how to write it. The class will have multiple properties that will need to be modified and accessed from another class. Here is an idea of what I'm trying to do:
class MyArrayClass {
private double[] myArray = {1.1, 2.2};
public double MyArray {
get { return myArray[index]; }
set { myArray[index] = value; }
}
}
class AnotherClass {
MyArrayClass mAC = new MyArrayClass();
mAC.MyArray[1] = 3.3;
}
Now that code doesn't work but I hope it expresses what I'm trying to do. I was able to achieve what I wanted using the below code (which does work) however it only works for one property within that class.
class MyArrayClass {
private double[] myArray = {1.1, 2.2};
public double this[int index] {
get { return myArray[index]; }
set { myArray[index] = value; }
}
}
class AnotherClass {
MyArrayClass mAC = new MyArrayClass();
mAC[1] = 3.3;
}
I'm also not sure how to define the values of different index positions without doing it multiple times, e.g.
mAC.MyArray[0] = 1.1;
mAC.MyArray[1] = 2.2;
As opposed to something such as:
mAC.MyArray[0, 1] = {1.1, 2.2};
Sorry if it's a mess but I hope it conveys what I'm trying to achieve.

Since you have several arrays, you need to expose several array-like indexable properties. Using your second MyArrayClass as an example, you can do it like this:
class MyTwoArrays {
private MyArrayClass array1 = ...;
private MyArrayClass array2 = ...;
public MyArrayClass Array1 {
get { return array1; }
}
public MyArrayClass Array2 {
get { return array2; }
}
}
Now you can use it like this:
MyTwoArrays two = new MyTwoArrays();
two.Array1[0] = 123.456;
two.Array2[0] = 789.432;

mAC.MyArray[0, 1] = {1.1, 2.2};
This is not the way it should be, it has to be done one by one. The way you're using would change it Two dimensional array, (somehow, it would be invalid, zero main elements and 1 element in each).
mAC.MyArray[0] = 1.1;
mAC.MyArray[1] = 2.2;
Is the valid way to set the arrays.
class MyArrayClass {
private double[] myArray = {1.1, 2.2};
public double this[int index] {
get { return myArray[index]; }
set { myArray[index] = value; }
}
}
class AnotherClass {
MyArrayClass mAC = new MyArrayClass();
mAC[1] = 3.3;
}
Code works because if the valid way of doing the process because only in this case, you're passing an actual index number to the array to return the value from. In the first code block, there was no Index number, and the return was an Array object.

If I understand correctly, you want your indexer to access 2 internal arrays representing heights and weights of animals.
class MyArrayClass {
private double[] heights = {1.1, 2.2};
private double[] weights = {1.1, 2.2};
public double[] this[int index] { //Or Tuple<double ,double>
get { return new double[] { heights[index], weights[index] }; }
set { heights[index] = value[0]; weights[index] = value[1]; }
}
}
If your intention is to access 2 numbers from 1 array, you can do that too.
class MyArrayClass {
private double[] myArray = {1.1, 2.2, 3.3, 4.4};
public double[] this[int index] {
get { return new double[] { myArray[index*2], myArray[index*2+1] }; }
set { myArray[index*2] = value[0]; myArray[index*2+1] = value[1]; }
}
}
This doesn't include checking the index or the argument (it can be null or have length < 2).
It might be more convenient in this case to have an Animal struct or something:
class MyArrayClass {
private Animal[] animals = {new Animal(1.1, 1.1), new Animal(2.2, 2.2)}
public Animal this[int index] {
get { return animals[index]; }
set { animals[index] = value; }
}
}

Related

Code snippet: create an "alias" for something else

I was looking for a similar way to create an alias for something else like its possible in C using preprocessor (this question is a bit similar, couldn't find anything useful there).
This is the problem: I've got a method that receives an array, but each position of the array has a specific meaning, like they where different parameters with specific names. What I want to do is to make my code easier to read (and write) by using those specific names, but, on the other hand, I don't want to create another method call (like in example 1) nor assign the array positions to new variables (example 2), because the performance is critical.
Example 1:
void OriginalMethodSignature(Type[] values)
{
SimplifiedMethod(values[0], values[1], ... values[n]);
}
void SimplifiedMethod(Type specificName1, Type specificName2, ... Type specificNameN)
{
// simple implementation using specific names instead of values[n]
}
Example 2:
void OriginalMethodSignature(Type[] values)
{
Type specificName1 = values[0];
Type specificName2 = values[1];
...
Type specificNameN = values[n];
// simple implementation using specific names instead of values[n]
}
I cannot change the method signature because its used in a dellegate, the Type is fixed.
The next example is a bit better, but still not optimum:
void OriginalMethodSignature(Type[] values)
{
// implementation using values[specificName1] ... values [specificNameN]
}
const int specificName1 = 0;
const int specificName2 = 1;
...
const int specificNameN = n-1;
Is there any way to create an snippet for this purpose? If yes, how would it be?
There isn't any built in way to do what you wan't, because you shouldn't really be doing it at all. You should be using an object with properties instead of an array.
Anyway, you can make an object that encapsulates the array, so that the properties use the array as storage:
public class NamedObject {
private Type[] _values;
public NamedObject(Type[] values) {
_values = values;
}
public SpecificName1 { get { return _values[0]; } set { _values[0] = value; } }
public SpecificName2 { get { return _values[1]; } set { _values[1] = value; } }
public SpecificName3 { get { return _values[2]; } set { _values[2] = value; } }
public SpecificName4 { get { return _values[3]; } set { _values[3] = value; } }
public SpecificName5 { get { return _values[4]; } set { _values[4] = value; } }
public SpecificName6 { get { return _values[5]; } set { _values[5] = value; } }
}
Now you can use the object to access the array:
void OriginalMethodSignature(Type[] values) {
NamedObject obj = new NamedObject(values);
// get a value
Type x = obj.SpecificName4;
// set a value
obj.SpecificName2 = x;
}
Create a dedicated class or struct, and parse the array into it.
public class MyClassOfStuff
{
Type SpecificName1 {get;set;}
Type SpecificName2 {get;set;}
public static MyClassOfStuff Parse(Type[] value)
{
Type specificName1 = values[0];
Type specificName2 = values[1];
...
Type specificNameN = values[n];
}
}
void OriginalMethodSignature(Type[] values)
{
var mystuff = MyClassOfStuff.Parse(values);
}

how can i get an access to the elements of array in the class

I have a problem which I don't know how to solve. I have a class. This class has two arrays. I would like to get access via properties. How can I do it? I tried to use indexers, but it is possible if I have only one array. Here what I want to do:
public class pointCollection
{
string[] myX;
double[] myY;
int maxArray;
int i;
public pointCollection(int maxArray)
{
this.maxArray = maxArray;
this.myX = new string[maxArray];
this.myY = new double[maxArray];
}
public string X //It is just simple variable
{
set { this.myX[i] = value; }
get { return this.myX[i]; }
}
public double Y //it's too
{
set { this.myY[i] = value; }
get { return this.myY[i]; }
}
}
With this code, my X and Y are only simple variables, but not arrays.
If I use indexers, I get access only to one array:
public string this[int i]
{
set { this.myX[i] = value; }
get { return this.myX[i]; }
}
But how can I get access to second array?
Or I can't use property in this case? And I need only use:
public string[] myX;
public double[] myY;
An example with Tuples.
public class pointCollection
{
Tuple<String,Double>[] myPoints;
int maxArray;
int i;
public pointCollection(int maxArray)
{
this.maxArray = maxArray;
this.myPoints = new Tuple<String,Double>[maxArray];
}
public Tuple<String,Double> this[int i]
{
set { this.myPoints[i] = value; }
get { return this.myPoints[i]; }
}
}
And to access the points you do...
pointCollection pc = new pointCollection(10);
// add some data
String x = pc[4].Item1; // the first entry in a tuple is accessed via the Item1 property
Double y = pc[4].Item2; // the second entry in a tuple is accessed via the Item2 property
If I got it right, you need some kind or read/write-only wrapper for arrays to be exposed as properties.
public class ReadWriteOnlyArray<T>{
private T[] _array;
public ReadWriteOnlyArray(T[] array){
this._array = array;
}
public T this[int i]{
get { return _array[i]; }
set { _array[i] = value; }
}
}
public class pointCollection
{
string[] myX;
double[] myY;
int maxArray;
public ReadWriteOnlyArray<string> X {get; private set;}
public ReadWriteOnlyArray<double> Y {get; private set;}
public pointCollection(int maxArray)
{
this.maxArray = maxArray;
this.myX = new string[maxArray];
this.myY = new double[maxArray];
X = new ReadWriteOnlyArray<string>(myX);
Y = new ReadWriteOnlyArray<double>(myY);
}
}
and usage
var c = new pointCollection(100);
c.X[10] = "hello world";
c.Y[20] = c.Y[30] + c.Y[40];
The closest you'll come without either changing your data structure or moving to methods is to make a property that returns each array, much like you did in your first code block, except without the [i].
Then, you do var x = instanceOfPointCollection.MyX[someI]; for example.

Populate a tree from a List of string arrays

I have list of arrays:
List<HeaderItem> _headerItems = new List<HeaderItem>();
class HeaderItem
{
private string[] _headers = new string[6];
public string this[int index]
{
get
{
return _headers[index];
}
set
{
_headers[index] = value;
}
}
}
Each of the 6 items in the array represent a level in the hierarchy. If all items matched in array position 0 then a single root level node would exist.
So,
A,B,C
A,B,D
B,C,D
B,D,E
would produce:
A
....B
........C
........D
B
....C
........D
....D
........E
etc....
Currently my solution is pretty hacked up and although it works I am trying to come up with a "cool" way of doing it.
You can achieve that by calling a print method recursively providing it with the subset of items to be printed and depth of the tree printed so far. I amended your class to contain a Length property so that the caller does not have to always assume it is 6. Also I added a constructor to make my initialization easy. Probably it wouldn't make sense in your code.
public class HeaderItem
{
public HeaderItem(string headers)
{
_headers = headers.ToCharArray().Select(x => x.ToString()).ToArray();
}
private string[] _headers = new string[6];
public int Length
{
get { return _headers.Length; }
}
//...
}
This is the print method. See how it does grouping and then calls itself recursively:
private static void PrintHeaders(IEnumerable<HeaderItem> headerItems, int depth = 0)
{
var result =
headerItems.Where(h => h.Length > depth)
.GroupBy(h => h[depth], h => h,
(k, g) => new {Key = k, Items = g})
.OrderBy(g => g.Key);
foreach (var pair in result)
{
Console.Write(new string('.', depth)); // change here to add more dots
Console.WriteLine(pair.Key);
PrintHeaders(pair.Items, depth + 1);
}
}
And this is how you can begin calling it:
PrintHeaders(_headerItems);
For testing, this is my Main method:
static void Main(string[] args)
{
_headerItems.Add(new HeaderItem("abc"));
_headerItems.Add(new HeaderItem("abd"));
_headerItems.Add(new HeaderItem("acd"));
_headerItems.Add(new HeaderItem("ace"));
_headerItems.Add(new HeaderItem("bce"));
_headerItems.Add(new HeaderItem("bcd"));
_headerItems.Add(new HeaderItem("bef"));
PrintHeaders(_headerItems);
Console.ReadLine();
}
And this is the result:
a
.b
..c
..d
.c
..d
..e
b
.c
..d
..e
.e
..f
When ever making tree always create a list of entity within that entity like this
class HeaderItem
{
private string[] _headers = new string[6];
private List<HeaderItem> _items;
public string this[int index]
{
get
{
return _headers[index];
}
set
{
_headers[index] = value;
}
}
public List<HeaderItem> Items
{
get
{
if (_items == null)
_items = new List<HeaderItem>();
return _items;
}
}
}

Assign values to arrays on structs using a comfortable code

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
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;
}
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.
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;
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;
}
}
}
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;
}
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?

c# program of Indexers

there is an error in this program.can anyone fix that?
Error is :TempRecord already defines a member called 'this' with the same parameters value
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication6
{
class TempRecord
{
// Array of temperature values
private float[] temps = new float[10] { 56.2F, 56.7F, 56.5F, 56.9F, 58.8F,
61.3F, 65.9F, 62.1F, 59.2F, 57.5F };
private int[] d= new int[10]{4,5,5,4,4,43,2,2,5,3};
// To enable client code to validate input
// when accessing your indexer.
//public int Length
//{
// get { return temps.Length; }
//}
// Indexer declaration.
// If index is out of range, the temps array will throw the exception.
public float this[int index]
{
get
{
return temps[index];
}
set
{
temps[index] = value;
}
}
public int this[int index]//error:TempRecord already defines a member called 'this' with the same parameters value
{
get
{
return d[index];
}
set
{
d[index] = value;
}
}
}
class Program
{
static void Main(string[] args)
{
TempRecord tempRecord = new TempRecord();
// Use the indexer's set accessor
tempRecord[3] = 58.3F;
tempRecord[5] = 60.1F;
// Use the indexer's get accessor
for (int i = 0; i < 10; i++)
{
System.Console.WriteLine("Element #{0} = {1}", i, tempRecord[i]);
}
Console.WriteLine(tempRecord[2]);
// Keep the console window open in debug mode.
System.Console.WriteLine("Press any key to exit.");
System.Console.ReadKey();
}
}
}
You have two members named this, that take the same parameters. That's not allowed in C# (or other .Net languages, as far as I'm aware).
You'd think you'd be able to do this if both members return different types, as yours do. But that would present the compiler with ambiguity. Which member would be called if you had code like this?
object x = tempRecord[3];
Make one or both indexers a method.
What you're trying to do is have 2 indexers with the same parameters and different return types. This is not legal in C#. You'll need to move at least one of them into a function
public int GetD(int index) {
return d[index];
}
public void SetD(int index, int value) {
d[index] = value;
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication6
{
class TempRecord
{
// Array of temperature values
private float[] temps = new float[10] { 56.2F, 56.7F, 56.5F, 56.9F, 58.8F, 61.3F, 65.9F, 62.1F, 59.2F, 57.5F }; private int[] d = new int[10] { 4, 5, 5, 4, 4, 43, 2, 2, 5, 3 };
public int Length //
{
get { return temps.Length; }
}
public float this[int index]
{
get { return temps[index]; }
set { temps[index] = value; }
}
}
class Program
{
static void Main(string[] args)
{
TempRecord tempRecord = new TempRecord();
tempRecord[3] = 58.3F;
tempRecord[5] = 60.1F;
for (int i = 0; i < 10; i++)
{
System.Console.WriteLine("Element #{0} = {1}", i, tempRecord[i]);
}
Console.WriteLine(tempRecord[2]);
System.Console.WriteLine("Press any key to exit.");
System.Console.ReadKey();
}
}
}
If you are trying some concept similar to overloading of functions, I'd like to say it never works with just a change in return type. Similar is the case of data members, where you have tried to use this with the same arguments but different return types.
The best method would be however (even for readability sake) making separate functions for the exclusive events that are being performed above.
I deleted the second data member above, replace it with the something like the foll. I think you better use temprecord.d[index Value] to access & use the member d from main.
public int d[int index]
{
get
{
return d[index];
}
set
{
d[index] = value;
}
}

Categories