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
Related
I want to access three members of a class (_orderDay, _orderCustody, _orderBox) according to and indexing variable (orderIndex), using a different approach than in the following example
public class COrdering
{
private int _orderDay;
private int _orderCustody;
private int _orderBox;
public COrdering() { _orderDay = _orderCustody = _orderBox = 0; }
public int IncOrder(int orderIndex)
{
int v = orderIndex == 0 ? _orderDay : (orderIndex == 1 ? _orderCustody : _orderBox);
v++;
if (orderIndex == 0) _orderDay = v
else if (orderIndex == 1) _orderCustody = v;
else _orderBox = v;
return v;
}
}
The idea is to use less coding than in the previous example. When I coded something like this in C++ I used std::bind to create a const array of references to each field involved, but I don't know how to make something similar in C#. Can anyone help me out with this?
EDIT
I've found a way to optimize IncOrder method:
//...
private int _incDay() { return ++_orderDay; }
private int _incCustody() { return ++_orderCustody; }
private int _incBox() { return ++_orderBox; }
private IReadOnlyList<Func<int>> _funcs = Array.AsReadOnly(new Func<int>[] {_incDay, _incCustody, incBox});
public int IncOrder(int orderIndex) { return _funcs[orderIndex](); }
There may be another way, such as creating an array of references to these fields, but I don't know if that's possible.
Sounds like a job for an index operator overload:
public int this[int index] => IncOrder(index);
Usage:
COrdering ordering = new COrdering();
int newValue = ordering[0];
Updated - you can use an array internally
public class COrdering
{
public enum OrderIndex { Day = 0, Custody = 1, Box = 2, NumElements };
private readonly int[] values = new int[(int)OrderIndex.NumElements];
public int IncOrder(OrderIndex orderIndex) => ++values[(int)orderIndex];
public int this[OrderIndex index] => IncOrder(index);
}
Also, your constructor can be removed, in C# everything is auto initialized to 0 (or null for reference types).
Why not use a Dictionary<int, int>?
public class COrdering
{
Dictionary<int, int> map = new Dictionary<int, int>();
public COrdering() { map[0] = 0; map[1] = 0; map[2] = 0; }
public int IncOrder(int orderIndex)
{
return ++map[orderIndex];
}
}
In fact you can even use an int[] or a List<int>.
I understand you want to simplify your code, so in that case start by the variables where you save data, if you are accessing them by index it would make more sense to declare an array and use an enum, something like this:
public class COrdering
{
enum OrderType
{
Day = 0,
Custody = 1,
Box = 2,
Count = 3
};
private int[] _order = new int[(int)OrderType.Count];
public int IncOrder(OrderType orderIndex)
{
// Increment corresponding order type and return its value
return ++_order[(int)orderIndex];
}
}
You can see that you implement your IncOrder with just one line of code. The ++ must be before the variable name, so you get the correct answer. I either use an intermediate variable for the increment or a ++ preceded of a good comment, so that the next programmer will see it.
The other solution with [] overload is unexpected and surprising for the next guy debugging your code :-) so that being said I suppose you guess which one I'd chose.
As far as I understand, the default type or argument passing in c# is by value. Therefore no statement is required. But when I try the run following code, my A matrix in Main is being modified by the operations done to dMatrixU in the Factorize() method of class Decomposition. I'm sure the problem is in the constructor of the Decomposition when I just assing A to dMatrixU, the reference of A is being assigned instead of the values. Therefore my question on how to avoid this, all I have found is how to pass the arguments by reference. Again, as I understand no modifier is needed for passing the argument by value. Where am I wrong?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using LinearEquations;
namespace Rextester
{
public class Program
{
public static void Main(string[] args)
{
double[,] A = new double[,]
{ { 1, 1, 1 } ,
{ 4, 3, -1 } ,
{ 3, 5, 3 } };
double[] B = new double[] {1,6,4};
Decomposition lu = new Decomposition(A,B);
lu.Factorize();
PrintMatrix(A,"A:");
PrintVector(B,"B:");
PrintMatrix(lu.L,"L:");
PrintMatrix(lu.U,"U:");
PrintVector(lu.D,"D:");
}
public static void PrintMatrix(double[,] M, String Title = "Matrix: ")
{
Console.WriteLine(Title);
for(int i = 0; i<M.GetLength(0); i++)
{
for(int j = 0; j<M.GetLength(1);j++)
{
Console.Write(M[i,j]+"\t");
}
Console.Write("\n");
}
Console.Write("\n");
}
public static void PrintVector(double[] V, String Title = "Vector: ",bool AsRow = true)
{
String str = (AsRow)? "\t" : "\n";
Console.WriteLine(Title);
for(int i = 0; i<V.GetLength(0); i++)
{
Console.Write(V[i]+str);
}
Console.WriteLine("\n");
}
}
}
namespace LinearEquations
{
public class Decomposition
{
// Fields
private double[,] dMatrixA; // Parameter in A*X=B
private double[] dVectorB; // Parameter in A*X=B
private double[] dVectorX; // Result wanted in A*X=B
private double[,] dMatrixU; // A splits into L and U
private double[,] dMatrixL; // L is used to calculate D in L*D=B
private double [] dVectorD; // D is used to calculate X in U*X=D
// Properties
public double[,] A
{
get { return dMatrixA; }
set { dMatrixA = value; }
}
public double[] B
{
get { return dVectorB; }
set { dVectorB = value; }
}
public double[] X
{
get { return dVectorX; }
set { dVectorX = value; }
}
public double[,] L
{
get { return dMatrixL; }
set { dMatrixL = value; }
}
public double[,] U
{
get { return dMatrixU; }
set { dMatrixU = value; }
}
public double[] D
{
get { return dVectorD; }
set { dVectorD = value; }
}
// Constructor
public Decomposition(double[,] A, double[] B)
{
dMatrixA = A;
dVectorB = B;
dVectorX = new double[B.Length];
dMatrixU = A;
dMatrixL = new double[A.GetLength(0),A.GetLength(1)];
dVectorD = new double[B.Length];
}
// Split A into L and U
public void Factorize()
{
// Iterate per each row
for(int i = 0; i<dMatrixU.GetLength(0); i++)
{
// For all the rows make element i equals 0
for(int j = i+1; j<dMatrixU.GetLength(0);j++)
{
// Factor that assures substraction makes 0
dMatrixL[1,1] = dMatrixU[j,i] / dMatrixU[i,i];
// Iterate per each column
for(int k = 0; k<dMatrixU.GetLength(1);k++)
{
dMatrixU[j,k] = dMatrixU[j,k] - dMatrixU[i,k]*dMatrixL[1,1];
}
}
}
}
}
}
As far is i understand, the default type or argument passing in c# is by value.
Unfortunately it is a bit more complicated and also has some execptions:
Reference types like Decomposition you hand in by making a copy of the reference. Unfortunately that means both still reference the same instance in memory. So despite a copy operation, it is call-by-Reference.
With value types like Int or double and their aliases, usually a copy is made. I do not know of any case where it does not, but I was wrong on those things before. So they are call by value.
Finally String and a few other reference types are inmutable by design. That has the advantage that they behave kinda like value types in this area. You hand in a Reference, but the instance itself can not be changed. The code can only create a new instance in memory with a different value. So despite handing over literal references, it kinda works like call by value.
Your specific case
Arrays are very explicitly Reference types. Handing them into a function without side effects, requires proper cloning. If it is a array of reference types, the cloning must be deep.
In your case you have arrays of value types. If you want to avoid call-by-reference side effects, you those arrays must be cloned. However as double is a value type, this cloning can be shallow. No need for a deep clone.
Unlike Java there is not a dedicated Clone() Method. And I am not sure why exactly. However you can often use one Collection to initialize another through the constructor. Or they even have a function like Array.Copy(), as TheBatman pointed out.
I am coding an application for my study, but i'm stuck at this point. I made a class called 'Neighborhood'. This class has a string and an int. In my main code I give the class a value and put it in a list. I now want to loop through my list and get the int out of it (put it in a listbox, or do a calculation). How do I get the int out of the list?
class Wijk
{
private string wijken;
private int tijd;
public string Wijken
{
get { return wijken; }
set { wijken = value; }
}
public int Tijd
{
get { return tijd; }
set { tijd = value; }
}
}
Created the list and the instance of the class.
List<object> Uden = new List<object>();
Wijk Wijkeninput = new Wijk();
Now I value the string and int with a combobox and textbox.
private void wijkAanmaken()
{
Wijkeninput.Wijken = Convert.ToString(cbWijken);
Wijkeninput.Tijd = Convert.ToInt16(tbSnelheid.Text);
Uden.Add(Wijkeninput);
}
For this, instead of having an object list, you can have list containing class objects like
List<Wjik> Uden = new List<Wjik>();
then you can access int as follows:
foreach (Wjik obj in listProgram)
{
int tij = Convert.ToInt32(obj.tijd);
}
First the List can be declared like this:
List<Wijk> Uden = new List<Wijk>();
To iterate over it:
foreach(var item in Uden)
{
var myInt = item.Tijd;
var myString = item.Wijken;
//here do whatever you want with the values
}
I have a class baseClass, and a list of objects of the baseClass. What i want to achieve is that i have to dynamically assign the instance number to each object in the list. for that what am doing is that use a constructor to do this.
Following is the class definition:
public class baseClass
{
private int _InstanceNumber;
private int _MyIntVal;
private string _MyString;
public string MyString
{
get { return _MyString; }
set { _MyString = value; }
}
public int MyIntVal
{
get { return _MyIntVal; }
set { _MyIntVal = value; }
}
public int MyProperty
{
get { return _InstanceNumber; }
}
public baseClass(int instance)
{
_InstanceNumber = instance;
}
}
The creation of the List of objects is as follows:
int instanceNumber = 0;
List<baseClass> classList = new List<baseClass>();
classList.Add(new baseClass(instanceNumber++) { MyString = "sample1", MyIntVal = 10 });
classList.Add(new baseClass(instanceNumber++) { MyString = "sample2", MyIntVal = 11 });
I know it is not the actual way for creating this. it does not give the index number actually. how can i calculate the instance number?
Consider the following scenario, that am creating another list of objects then it hard to maintain the instance number. or if i create another object(this also be an instance) external to the list.
int instanceNumber = 0;
List<baseClass> anotherClassList = new List<baseClass>();
classList.Add(new baseClass(instanceNumber++) { MyString = "sample1", MyIntVal = 10 });
classList.Add(new baseClass(instanceNumber++) { MyString = "sample2", MyIntVal = 11 });
Updates:
This is my temporary solution for this. i need proper way/ method to maintain instance number
If you want to find the index of item in the list, you should ask it from the list, not the item like:
var index = list.IndexOf(item);
But it seems that you expect the item to be aware of its position in the list. In order to do this, you should pass the list to the item so it can use it to find its own place in it:
public class Item
{
private List<Item> _containerList;
public Item(List<Item> containerList)
{
_containerList = containerList;
}
public int InstanceNumber
{
get { return _containerList.IndexOf(this); }
}
}
and change your code to:
List<Item> classList = new List<Item>();
classList.Add(new Item(classList ) { ... });
classList.Add(new Item(classList ) { ... });
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;