How to make a arrayclass access with this[][] - c#

I want to create an Matrix class for some calculations. At my research i was stumble over some performance discussions Array[,] vs Array[][] and they conclusion was always use Array[][] if you want it fast
When i'm trying to provide access to an value via [][] it seems like i miss something important because i cant create an property like this
public double this[int iRow][int iCol]
{
get { return matrix[iRow][iCol]; }
set { matrix[iRow][iCol] = value; }
}
my problem is the second [] because the following works well
public double this[int iRow,int iCol]
{
get { return matrix[iRow][iCol]; }
set { matrix[iRow][iCol] = value; }
}
So what do i need to add in this class to let it work with [][] ?
public class Matrix
{
private bool _isSquare;
private double[][] matrix;
public double this[int iRow,int iCol]
{
get { return matrix[iRow][iCol]; }
set { matrix[iRow][iCol] = value; }
}
}

You can't do this in one class.
var b = a[1][2];
is the same as
var temp = a[1];
var b = temp[2];
They are two separate indexing operations.
Your first indexer would need to return an instance of some class that also has an indexer.
Using Indexers (C#)

Not sure what you are trying to do but if your matrix was the following you could still do what you are looking for
public class M
{
public double[][] Matrix { get; private set; }
public M()
{
Matrix = new double[2][]{new double[2], new double[2]};
}
}
M n = new M();
n.Matrix[0][0] = 1.0;

Related

In C# is there a way to use properties with arrays?

The way I understand it, C# properties are methods that have the get and set accessors.
class MyClass
{
private int x;
public int X
{
get
{
return x;
}
set
{
x = value;
}
}
}
I can call the property of the class in a script (and its accessors) with
MyClass mc = new MyClass();
mc.X = 10;
Debug.Log(mc.X); //returns 10
To my knowledge, however, I can pass only one value to the property.
Is there a way to pass arrays? Something like
MyClass mc = new MyClass();
mc.X = new int[] { 1, 2 }; //throws an error
Debug.Log(mc.X[0]); //I'd like it to return 1
This throws an error of course. I wonder if it's possible to do it any other way.
The solution is simple - use int[] instead of int
class MyClass
{
private int[] x;
public int[] X
{
get
{
return x;
}
set
{
x = value;
}
}
}
Also you might consider using auto property instead just like this:
class MyClass
{
public int[] X { get; set; }
}
You might also want to take a look at the Lists and read some basics ;)
Sure, just make the property an array or list also:
class MyClass
{
// in general a list should never be null, but could be empty, or without values.
// thats why we initialize the field here
private List<int> x = new List<int>();
public List<int> X
{
get
{
return x;
}
set
{
x = value;
}
}
}
then you could do:
var obj = new MyClass();
obj.X.Add(3);
obj.X.Add(6);
// (or use AddRange() to add another list or array of values
// Then loop the list and output values:
foreach(int x in obj.X)
{
Console.WriteLine(x);
}
Here's a dotnetfiddle for the above code:
https://dotnetfiddle.net/T2FrQ0

Concatenating two arrays results in two modified arrays instead of one C#

I have a very strange Behavior when merging two arrays together:
Assumptions
I have a class Tensor which contains an array float[] and a function AddTensorElements:
class Tensor
{
public float[] MovingAverage3h { get; set; }
public float[] MovingAverage6h { get; set; }
public float[] MovingAverage1d { get; set; }
public void AddTensorElements(Tensor input)
{
if (this.MovingAverage3h == null)
this.MovingAverage3h = input.MovingAverage3h;
this.MovingAverage6h = input.MovingAverage6h;
this.MovingAverage1d = input.MovingAverage1d;
}
else
{
this.MovingAverage3h = Concat(this.MovingAverage3h, input.MovingAverage6h);
this.MovingAverage6h = Concat(this.MovingAverage6h, input.MovingAverage6h);
this.MovingAverage1d = Concat(this.MovingAverage1d, input.MovingAverage1d);
}
private float[] Concat (float[] first, float[] second)
{
List<float> concatenated = new List<float>();
concatenated.AddRange(first);
concatenated.AddRange(second);
//foreach (float value in first) concatenated.Add(value);
//foreach (float value in second) concatenated.Add(value);
float[] returnArray = concatenated.ToArray();
return returnArray;
}
}
Within my main program, I repeatedly add the tensor M6t to the base tensor Minutes30[i]
class TensorCreator
{
private static List<Elements.Tensor> Minutes30 = new List<Elements.Tensor>();
private static void AddValues(Tensor M6t)
{
// Fill Minutes 30
Minutes30.Add(M6t);
for (int i = CounterM30; i < Minutes30.Count-1; i += M6)
{
{ } // Issue come up right here
Minutes30[i].AddTensorElements(M6t);
{ } // Issue come up right here
}
}
public static void AppendDataToTensor(Elements.Tensor queueElement)
{
// ...
AddValues(M6Avg);
}
}
Expected behavior vs actual behavior
The array within Minutes[i] expands
The array within M6t staysfloat[1]
So far so good, this works in a tiny separate test application
Within my actual application, the same code lets the baseTensor expand but also the input tensor gets expanded!
for (int i = CounterM30; i < Minutes30.Count-1; i += M6)
{
// M6T.Length == 1;
Minutes30[i].AddTensorElements(M6t);
// M6T.Length == Minutes30[i].Length;
}
strangely, whitin AddtensorToElements() I can see the values changing as well:
The Issue lies right here:
Minutes30.Add(M6t);
This adds a reference of Class Tensor M6t to Minutes 30. The result is that Minutes30[i] gets concatenated with it self.
Solution:
In class Tensor, add a Clone() method
public Tensor Clone()
{
Tensor tensor = new Tensor();
tensor.MovingAverage3h = this.MovingAverage3h.ToArray();
tensor.MovingAverage6h = this.MovingAverage6h.ToArray();
tensor.MovingAverage1d = this.MovingAverage1d.ToArray();
return tensor;
}
then change
Minutes30.Add(M6t);
to
Minutes30.Add(M6t.Clone());

Can't access class field in another class

public class Vector
{
public int[] row = new int[2];
public Vector(int x, int y)
{
this.row[0] = x;
this.row[1] = y;
}
public int[] Row
{
get
{
return row;
}
}
}
public class Matrix<Vector>
{
public Vector[] rows = new Vector[2];
public Matrix(Vector v1, Vector v2){
this.rows[0] = v1;
this.rows[1] = v2;
}
public void Transform()
{
foreach (Vector v in rows)
{
Console.WriteLine(v.row[0]);
}
}
}
I'm getting 'Vector' does not contain a definition for 'row' and I have no idea why. It's set to public and I'm iterating over vector objects. What am I doing wrong here?
This is my first time using c#, coming from python so please don't mind the code if it doesn't make sense. Just toying with classes and syntax
here as you have written in your question,
public class Matrix<Vector>
means, your class Matrix is generic, and whatever type you will pass while creating an instance of Matrix, code of this class will take that type as Vector .
Note that your class Vector is total different type than the type Vector in Matrix class.
For ex.
if your create an object of matrix like this,
Matrix<string> m = new Matrix<string> ("amit", "maheshwari");
this will be valid and for this instacne of Matrix, Vector will be string. and yes string does not contain a definition for 'row' and so does Vecotr.
So, maybe you are misusing this class.
Or if you have created this class by your self and you want to perform what you have shown in question, there is no need to make this class generic.
public class Matrix
{
//so now this array of vector will be of class Vector
public Vector[] rows = new Vector[2];
public Matrix(Vector v1, Vector v2){
this.rows[0] = v1;
this.rows[1] = v2;
}
public void Transform()
{
foreach (Vector v in rows)
{
Console.WriteLine(v.row[0]);
}
}
}
public class Matrix<TVector> where TVector : Vector
{
public TVector[] rows = new TVector[2];
public Matrix(TVector v1, TVector v2)
{
this.rows[0] = v1;
this.rows[1] = v2;
}
public void Transform()
{
foreach (TVector v in rows)
{
Console.WriteLine(v.row[0]);
}
}
}
Thank you for John and other friends for reply quick answer. you must use TVector.

Avoid expanding linked objects when serialising

I am using JSON.NET to serialize some c# objects into JSON (and then write to a file).
My two main classes are:
public class Reservoir {
private Well[] mWells;
public Well[] wells {
get { return mWells; }
set { mWells = value; }
}
}
and
public Well() {
private string mWellName;
private double mY;
private double mX;
public string wellName {
get { return mWellName; }
set { mWellName = value; }
}
public double y {
get { return mY; }
set { mY = value; }
}
public double x {
get { return mX; }
set { mX = value; }
}
private Well[] mWellCorrelations;
}
The problem is that the output looks like:
'{"wells":[{"wellName":"B-B10","y":217.04646503367468,"x":469.5776343820333,"wellCorrelations":[{"wellName":"B-B12","y":152.71005958395972,"x":459.02158140110026,"wellCorrelations":[{"wellName":"B-B13","y":475.0,"x":495.14804408905263,"wellCorrelations":[{"wellName":"B-B11","y":25.0,"x":50.0,"wellCorrelations":[]}
i.e. the associated wells of each well object are expanded as objects themselves and this becomes a serious problem of space and time when there lots of associated objects.
I suppose I would have preferred something like:
'{"wells":[{"wellName":"B-B10","y":217.04646503367468,"x":469.5776343820333,"wellCorrelations":[{"wellName":"B-B12"}], {"wellName":"B-B11","y":217.04646503367468,"x":469.5776343820333,"wellCorrelations":[{"wellName":"B-B13"}
i.e maintaining only the well name as the link (assume its unique).
Is there a way to do this with JSON.NET?
You have set
serializer.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
but it doesn't make any difference.
You could add a new readonly property called WellCorrelations that only got the names of the well correlations, and slap a JsonIngore attribute on your mWellCorrelations, like so:
[JsonIgnore]
private Well[] mWellCorrelations;
public string[] WellCorrelations
{
get { return mWellCorrelations.Select(w => w.wellName).ToArray(); }
}
http://james.newtonking.com/projects/json/help/html/ReducingSerializedJSONSize.htm
That way, the serializer will only serialize the names of the correlated wells.

How to design collection in C#

I have a class MySet
class MySet
{
.......
}
This class will declare a reference to another type
(i.e)
class MySubSet
{
....
}
The purpose of the type MySubset is to supply "subset id" and a collection of integers to
the type MySet.
Which one of the followings is the correct implementation
(1)
class MySet
{
int mySetID;
MySubSet subset = new MySubSet();
public int MySetID
{
get { return mySetID; }
set { mySetID = value; }
}
public MySubSet MySubSet
{
get { return subset; }
set { subset = value; }
}
}
class MySubSet
{
int subsetID;
List<int> subset = new List<int>();
public List<int> SubSet
{
get { return subset; }
set { subset = value; }
}
public int SubSetID
{
get { return subsetID; }
set { subsetID = value; }
}
}
(2)
class MySet
{
int mySetID;
AnotherSubSet subset = new AnotherSubSet();
public int MySetID
{
get { return mySetID; }
set { mySetID = value; }
}
public AnotherSubSet MySubSet
{
get { return subset; }
set { subset = value; }
}
}
class AnotherSubSet : List<int>
{
int subsetID;
List<int> lst = new List<int>();
public int SubSetID
{
get { return subsetID; }
set { subsetID = value; }
}
}
If both are worst design consideration help me to implement the one that I could follow.
MySet doesn't look like a collection to me. It's just a class.
I'd rename it to ´MyEntity´or something like that.
List<MyEntity> mySet = new List<MyEntity>();
From all the information you've provided, I would do this:
public class MyEntity
{
public int ID { get; set; } // shortcut
public List<int> Numbers = new List<int> { get; set; } // shortcut
}
Sorry, I don't have /Net3.0 to hand so can't check the constructor of the list with the shortcut get/set but its the theory that counts...
The first version is better (as improved upon by ck) - use composition instead of inheritance. You are advised not to add properties to collections, which is effectively what you're doing in version 2. Collections should contain their items only. Someone else may be able to expand on the reasons for this, as I am not an expert, but it does cause serialization problems.
Number 2 is better, use inheritence not composition for this pattern, - because fundementally, it is a collection. It does not contain a collection. Inheritance gives you all the functionality of the base class without the need to write pass-through functions. If you want to add a new item to the collection, using composition, you either have to add a pass through method for the Add() method to class MySubSet:
class MySubSet
{
int subsetID;
List<int> subset = new List<int>();
public List<int> SubSet
{
get { return subset; }
set { subset = value; }
}
public void Add(int i) { subset.Add(i); } // pass through to subset.Add()
}
or you have to use the following non-intuitive and confusing syntax...
MySet.MySubSet.SubSet.Add(67);
with inheritence, all you need is
MySet.MySubSet.Add(67);

Categories

Resources