diplaying data in private array by using indexers in c# - c#

I am declaring two private arrays in indexes and displaying the data in main. However, it is not displaying any one tell me how to display the data in the two private arrays in indexers?
class Program
{
static void Main(string[] args)
{
student sc = new student();
for (int i = 0; i < sc.mlength; i++)
{
Console.WriteLine(sc[i]);
}
Console.ReadLine();
//i am declaring two private arrays in indexes and displaying the data in main is not displaying any one tell me how to display the data in the two private arrays in indexers?
}
}
public class student
{
private int[] _marks = new int[] { 60, 68, 70 };
private string[] _names = new string[] { "suri", "kumar", "suresh" };
public int this[int i]
{
get
{
return _marks[i];
}
set
{
_marks[i] = value;
}
}
public string this[int i]
{
get
{
return _names[Convert.ToInt32(i)];
}
set
{
_names[Convert.ToInt32(i)] = value;
}
}
public int mlength
{
get
{
return _marks.Length;
}
}
public int nlenght
{
get
{
return _names.Length;
}
}
}
}

Indexers allow your class to be used just like an array. On the inside of a class, you manage a collection of values any way you want. These objects could be a finite set of class members, another array, or some complex data structure. Regardless of the internal implementation of the class, its data can be obtained consistently through the use of indexers. Here’s an example.
Example:
using System;
class IntIndexer
{
private string[] myData;
public IntIndexer(int size)
{
myData = new string[size];
for (int i=0; i < size; i++)
{
myData[i] = "empty";
}
}
public string this[int pos]
{
get
{
return myData[pos];
}
set
{
myData[pos] = value;
}
}
static void Main(string[] args)
{
int size = 10;
IntIndexer myInd = new IntIndexer(size);
myInd[9] = "Some Value";
myInd[3] = "Another Value";
myInd[5] = "Any Value";
Console.WriteLine("\nIndexer Output\n");
for (int i=0; i < size; i++)
{
Console.WriteLine("myInd[{0}]: {1}", i, myInd[i]);
}
}
}
The IntIndexer class has a string array named myData. This is a private array that external users can’t see. This array is initialized in the constructor, which accepts an int size parameter, instantiates the myData array, and then fills each element with the word “empty”.
The IntIndexer class has a string array named myData. This is a private array that external users can’t see. This array is initialized in the constructor, which accepts an int size parameter, instantiates the myData array, and then fills each element with the word “empty”.
The next class member is the Indexer, which is identified by the this keyword and square brackets, this[int pos]. It accepts a single position parameter, pos. As you may have already guessed, the implementation of an Indexer is the same as a Property. It has get and setaccessors that are used exactly like those in a Property. This indexer returns a string, as indicated by the string return value in the Indexer declaration.
The Main() method simply instantiates a new IntIndexer object, adds some values, and prints the results. Here’s the output:
Indexer Output
myInd[0]: empty
myInd[1]: empty
myInd[2]: empty
myInd[3]: Another Value
myInd[4]: empty
myInd[5]: Any Value
myInd[6]: empty
myInd[7]: empty
myInd[8]: empty
myInd[9]: Some Value

Related

Passing array by value in c#

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.

Returning a reference of a struct instead of a copy on C# 3.0?

I have this code:
using System;
using System.Collections.Generic;
using UnityEngine;
public interface HaveId
{
int id { get; }
}
public struct BusinessData : HaveId
{
// business type data
public int graphic_asset_id;
public string name;
public int id { get; set; }
}
public class LookupHelper<T> where T: HaveId
{
private T[] _list;
public T[] list
{
get { return _list; }
set { _list = value; _mapToDictionary(); }
}
private Dictionary<int, int> idxById = new Dictionary<int, int>();
public LookupHelper(){}
private void _mapToDictionary()
{
if(idxById.Count > 0) idxById = new Dictionary<int, int>();
for(var z =0 ; z < list.Length; ++z)
{
idxById[list[z].id] = z;
}
}
public bool IsIdExists(int id)
{
return idxById.ContainsKey(id);
}
public T ById(int id) // is this a reference?
{
var idx = idxById[id];
if (idx >= list.Length) throw new Exception(
String.Format("Invalid Index: {0} >= {1} on {2}",idx.ToString(),list.Length.ToString(), typeof(T).Name)
);
return list[idx];
}
}
And the test code:
LookupHelper<BusinessData> bd = new LookupHelper<BusinessData>();
bd.list = new BusinessData[]
{
new BusinessData{id = 1, name = "test"},
new BusinessData{id = 2, name = "test2"},
};
bd.ById(1).name = "foo";
This give an error: "Cannot modify struct member when accessed struct is not classified as a variable"
How can I change the value of first BusinessData and keep the array still allocated on a contiguous memory (array of struct, needed for cache locality)?
This should be a simple matter of splitting it up into a few lines. Extract the object to get a copy, modify the copy, then overwrite it in the array:
BusinessData bsd = bd.ById(1);
bsd.name = "foo";
bd.SetById(1, bsd);
Of course, you'll need to write that SetById method to reinsert things into the array:
public void SetById(int id, T obj)
{
Int32 idx = idxById[id];
list[idx] = obj;
}
As you know C# borrowed something’s from C and Java. But not everything.
In C, you can create a place for struct on the stack or the heap. On the heap, I can then pass a pointer around and change the content. Very powerful.
But C# emphasizes ease of memory management via garbage collection. To make it easy, C# has the concept of boxing value types into System.Object. Additional details, can be found on Microsoft C# Programming Guide on Boxing and unboxing.
So when you access the value type in your list, you have to explicitly unbox the value. Therefore it’s a copy of the item in the list. You can do what #Nyerguds suggested.
But to make life easy, why not turn your BusinessData into a class?

Class wrapper for data lists

I need some help building a fluent interface (class wrapper) that allows me to create (and name) a 2D double array from curve sets in a database (in myWell). Ideally, a user could create a 2D double array when executing the following syntax (or something similar):
Double [,] CurveDoubleName = CreateIPmathCurves.CreateCurve(comboBox1.Text).CurveName("NPHIL").Make()
Where comboBox1 data comes from a WindowsForm called frmMain. Here's what I have so far:
namespace UserProgram
{
public class CreateIPmathCurve : frmMain, ICanNameCurve, ICanLocateCurve, ICanMakeCurve
{
private string _comboBoxName;
private string _CurveName;
private string _data;
// Private constructor - Only allow instantiated functions to create an IP math Curve
private CreateIPmathCurve()
{ }
// Instantiating functions
public static ICanNameCurve CreateCurve()
{
return new CreateIPmathCurve();
}
// Chaining functions
private CreateIPmathCurve(string data) { _data = data; } //private constructor prevents instantiation of your builder
public ICanLocateCurve SetCurveName(string CurveName)
{
_CurveName = CurveName;
return this; // this allows chaining.
}
public ICanMakeCurve SetComboBoxName(string comboBoxName)
{
_comboBoxName = comboBoxName;
return this; // this allows chaining.
}
// ending functions
public DataObject CreateCurveDoublArrayObj(string comboBoxName)
{
try
{
// User will need to populate comboBox.. example: comboBox1.text
char[] delimiter = { ':' };
Curve1inText = comboBoxName;
string[] crvIn1 = Curve1inText.Split(delimiter);
string CurveSet = crvIn1[0];
string Curve = crvIn1[1];
ICurveSet InCurveSet = myWell.FindCurveSet(CurveSet);
ICurve InMyCurve = myWell.FindCurve(Curve);
if (InMyCurve == null)
{
MessageBox.Show("You need to input a curve");
}
ILogReading[] In = InMyCurve.LogReadings.ToArray();
double[,] CurveDouble = new double[In.Length, 2];
int j = 0;
foreach (ILogReading reading in InMyCurve.LogReadings)
{
CurveDouble[j, 0] = reading.Depth;
CurveDouble[j, 1] = reading.Value;
j++;
}
return new DataObject(CurveDouble);
}
catch (Exception ex)
{
MessageBox.Show("Error building Double Array\n" + ex.Message + "\n" + ex.StackTrace);
return null;
}
}
public double[,] MakeCurve()
{
//this is where CurveName input ("NPHIL") should name the 2D double array listed from dataobject.
// I receive a "non-invocable member 'DataObject' cannot be used like a method" error....
_CurveName = DataObject(_comboBoxName);
return this;
// I also receive a "cannot implicity convert type UserProgram.CreateIPmathCurve' to 'double [*,*]"...
}
}
// using interfaces to enforce Fluent Interface grammar -- can't make curve if you don't know the location of curve, etc...
public interface ICanNameCurve
{
ICanLocateCurve SetCurveName(string CurveName);
}
public interface ICanLocateCurve
{
ICanMakeCurve SetComboBoxName(string comboBoxName);
}
public interface ICanMakeCurve
{
DataObject CreateCurveDoublArrayObj(string comboBoxName);
}
}
Can you help me create a CurveName() function that would allow the user to name the dataobject? (I tried a getter-setter accessor, but I don't think I was doing it correctly or am lacking a strong conceptual understanding of how it all works)
Lastly, can you also help me create a Make() function that puts all of this together?
To build a fluent API, you need to find a way to aggregate all data until your call to Make.
A simple way is to write a Builder, which holds all data. This builder has setter methods for every configurable field.
The key point here is that each setter method returns the Builder object, allowing you to chain calls.
public class FluentCurveBuilder
{
private string _name;
private string _data;
private string _color;
private FluentCurveBuilder(string data) { _data = data; } // private constructor prevents instantiation of your builder
public FluentCurveBuilder SetName(string name)
{
_name = name;
return this; // this allows chaining.
}
public FluentCurveBuilder SetColor(string color)
{
_color = color;
return this; // this allows chaining.
}
public static FluentCurveBuilder CreateCurve(string data)
{
return new FluentCurveBuilder(data);
}
public Curve Make()
{
// Creation logic goes here
}
}
You now can use the builder to configure your curve.
var curve = FluentCurveBuilder.CreateCurve("Data")
.SetName("Test")
.Make();
We have a static CreateCurve method, which returns a new builder. All other methods should only store the data in an instance field and return this builder.
In the Make method, you now have access to all previous aggregated data and you can construct your Curve
I think I was over analyzing my problem - The simple solution would be to create a method that returns the 2D double array and then assign a name to the object when I invoke the function... so using this:
public double [,] CreateIPmathCurve(string comboBoxName)
{
string CurveInText = "";
char[] delimiter = { ':' };
CurveInText = comboBoxName;
string[] crvIn = CurveInText.Split(delimiter);
string CurveSet = crvIn[0];
string Curve = crvIn[1];
ICurveSet InCurveSet = myWell.FindCurveSet(CurveSet);
ICurve InMyCurve = myWell.FindCurve(Curve);
if (InMyCurve == null)
{
MessageBox.Show("You need to input a curve");
}
ILogReading[] In = InMyCurve.LogReadings.ToArray();
double[,] CurveDouble = new double[In.Length, 2];
int j = 0;
foreach (ILogReading reading in InMyCurve.LogReadings)
{
CurveDouble[j, 0] = reading.Depth;
CurveDouble[j, 1] = reading.Value;
j++;
}
return CurveDouble;
Allows me to create the array with this:
double[,] NPHIL = CreateIPmathCurve(comboBox1.Text);
Thanks to everyone who helped me in this endeavor!

Store array of classes in a list

I have a class as below,
class EUInput
{
public EUInput()
{
RtID = 0;
}
public int RtID { get; set; }
}
I want to store this class with different RtID values in a list. I tried as below,
static void Main(string[] args)
{
EUInput clsEUInput = new EUInput();
List list = new List();
for (int i = 0; i < 5; i++)
{
clsEUInput.RtID = i;
list.Add(clsEUInput);
}
foreach (EUInput obj in list)
{
Console.WriteLine(obj.RtID.ToString());
}
Console.ReadLine();
}
I am getting an output as
4
4
4
4
4
But I need an outupt as
0
1
2
3
4
You need to move the declaration of clsEUInput inside the for loop. Right now, there is only one EUInput object and you're adding the same object to the list multiple times.
List list = new List();
for (int i = 0; i < 5; i++)
{
EUInput clsEUInput = new EUInput();
clsEUInput.RtID = i;
list.Add(clsEUInput);
}
Change EUInput to be a struct (and keep your Main method as it is):
public struct EUInput
{
public int RtID;
}
A struct is a value type (a class is a reference type), so when you add it to a list, you basically add a "copy" of the whole structure (and not just a reference). So when you keep changing the RtID in the loop, you still change that one object you created, but the objects in the list won't be affected.
Either your boss is playing a trick on you, i.e. want's to test your knowledge about value types and reference types, or he doesn't know about the difference between them himself...
you Need new instances to the class
or the complete list will hold references to the one instance
private class EUInput
{
public EUInput()
{
RtID = 0;
}
public int RtID { get; set; }
}
//I want to store this class with different RtID values in a list. I tried as below,
private static void Main(string[] args)
{
List<EUInput> list = new List<EUInput>();
for (int i = 0; i < 5; i++)
{
EUInput clsEUInput = new EUInput();
clsEUInput.RtID = i;
list.Add(clsEUInput);
}
foreach (EUInput obj in list)
{
Console.WriteLine(obj.RtID.ToString());
}
Console.ReadLine();
}

encapsulation of an array of objects c#

I would like to create an array of objects. Each object has it's own int array.
For each object I assign values to it's array ONLY with keys given by myself (example: li[i].V[10] = 1; li[i].V[50] = 10; )
Can someone tell me how to do that? Can I do that without using Lists?
The second case is analogical to first. I would like to know how to assign values of object's List
using setter.
I tried to do that by myself. Unfortunately My code crashed cuz I don't know how to set the dimension of V and Word:
class CFiles
{
//private int[] v=new int[5];//dont want to specify the dimention of array here
private int[] v;//vector of file
private List<string> words;
public CFiles()
{
words = Words;
v = new int[50];
v = V;
}
public int[] V { get; set; }
public List<string> Words { get; set; }
}
class Program
{
static void Main(string[] args)
{
CFiles[] li = new CFiles[2];
for(int i=0;i<li.Length;i++)
{
li[i]=new CFiles();
li[i].V[10] = 1;
li[i].V[50] = 10;
li[i].V[50] = 15;
li[i].Words.Add("a");
li[i].Words.Add("ab");
li[i].Words.Add("abc");
}
for (int i = 0; i < li.Length; i++)
{
for(int j=0;j<li[i].V.Length;j++)
{
Console.WriteLine(li[i].V[j]);
}
}
Console.WriteLine();
}
}
Your constructor isn't right and your properties aren't quite right. You might want something more like this:
class CFiles
{
//private int[] v=new int[5];//dont want to specify the dimention of array here
private int[] v;
public int[] V { get { return v; } set { v = value; } }
private List<string> words;
public List<string> Words { get { return words; } set { words = value; } }
public CFiles()
{
words = new List<string>();
v = new int[51]; //needs to be 51 if you are going to assign to index 50 below
}
}
Other than those issues, your code seems to do what you want. You have an array of objects where each object has its own int array (in addition to a string of strings).
Is that not what you want?

Categories

Resources