How can I reference a 3D array from another class? - c#

In the main program class I have:
static void Main()
{
string[,,] anArray = new string [3,3,3];
anArray[0,0,0] = "value1";
anArray[0,0,1] = "value2"; .... //filling the rest of the array.
}
How can I pass this array into another separate class "anotherClass" using a constructor with multiple arguments like:
class AnotherClass
{
private string[,,] anotherClassArray;
public string[,,] AnotherClassArray
{
get { return anotherClassArray;}
}
public AnotherClass (string[,,] fromAnArray)
{
anotherClassArray = new string [fromAnArray.Length];
}
}
I've seen examples with just a simple 1 dimensional array being passed from the Main program into another separate class and back again but when I tried following the same example for a multidimensional I get the error:
"Cannot implicitly convert type 'string[]' to 'string[,,*]'" when trying to initialize the new array.

If you want AnotherClass to have it's own separate, empty, instance of a 3D array, then you can do what Pikoh said. In this case, if you change the contents of the array, the original array created in Main is unaffected, and vice versa.
If you want AnotherClass to reference the same array as the one created in Main, and therefor have access to it's same, filled in contents, then simply set the AnotherClass.anotherClassArray reference to equal fromAnArray in the AnotherClass constructor like so:
public AnotherClass (string[,,] fromAnArray)
{
anotherClassArray = fromAnArray;
}

You can do it like this:
string[, ,] anotherClassArray = new string[anArray.GetLength(0),
anArray.GetLength(1),
anArray.GetLength(2)];
Update
As a experiment, if you want make this to generic for any unknown number of dimensions, you can use this method:
private Array CreateArrayWithSameDimensions(Array inArray)
{
int[] lengths = new int[inArray.Rank];
for (int i = 0; i < inArray.Rank; i++)
{
lengths[i] = inArray.GetLength(i);
}
Array myArray = Array.CreateInstance(typeof(string), lengths);
return myArray;
}
The problem with this approach is that accessing this array is not as simple as with known dimensions. This is an example of usage:
Array myArray = CreateArrayWithSameDimensions(anArray);
int[] indices = new int[anArray.Rank];
for (int i = 0; i < anArray.Rank; i++)
{
indices[i] = 0;
}
myArray.SetValue("test", indices);
This would set test in the lower bound index of that array. If the input array was a 3 dimensional array, in myArray[0,0,0] we would have test.

Related

Returning an Array Manipulates Original Value in C#

This is my first question on the site and I am sure I'll find my answer here.
For school, I was trying to do some basic C# coding for a challenge that was given to us.
Here is the problem:
Normally when I pass a value through a method I don't run into issues. Like so:
static void Main(string[] args)
{
// Declare Integer
int originalInt = 20;
// Call the Method
int multipliedInt = Multiplication(originalInt);
// Prompt
Console.WriteLine("Original: {0} Modified: {1}", originalInt, multipliedInt);
}
// Method
static public int Multiplication(int original)
{
// Quik Maffs
int modifiedValue = original * 2;
return modifiedValue;
}
The above example works just fine. The original value is 20 and the modified value is 40.
However, this changes when I attempt to do that with an array:
static void Main(string[] args)
{
// Declare Original Array
int[] originalArray = new int[] {1, 4, 6, 8, 12};
// Call Method
int[] multipliedArray = Multiplication(originalArray);
// Prompt
Console.WriteLine("Original: [{0}], Multiplied: [{1}]", String.Join(", ", originalArray), String.Join(", ", multipliedArray));
}
// Method
static public int[] Multiplication(int[] original)
{
// New Int
int[] modified = original;
// Loop
for (int i = 0; i < modified.Length; i++)
{
modified[i] *= 2;
}
return modified;
}
The code above returned the modified value twice. It seems like it modifies the original value as well.
Any idea why this is happening?
int is a value type. When you pass a value type to a method, you pass a copy of the value.
Arrays are reference types. When you pass a reference type to a method, you pass a copy of the reference... but both the copy and original still refer to the same object.
Now it seems you may have understood this much, because of this code:
(This is why I re-opened the question... the stock ref-vs-value answer wasn't gonna cut it here)
int[] modified = original;
However, the other thing that happens with reference types is assignments also only copy the reference. So modified and original in that snippet again refer to the same array object.
To fix this, you need to make an actual deep copy of the array. There are several ways to do this. I would tend to write the method this way:
static public IEnumerable<int> Multiplication(IEnumerable<int> original)
{
return original.Select(i => i * 2);
}
...and append a .ToArray() at the end of the method call if and only if I really need a full array (hint: very often it turns out you don't), like this:
int[] multipliedArray = Multiplication(originalArray).ToArray();
or like this:
var multipliedArray = Multiplication(originalArray);
But I understand there are a number of things here that aren't very familiar to a beginner. You might try something more like this:
static public int[] Multiplication(int[] original)
{
int[] modifed = new int[original.Length];
for (int i = 0; i < original.Length; i++)
{
modified[i] = original[i] * 2;
}
return modified;
}

Why is my C# object null after I have instantiated it? (Or have I not done that properly?)

Why is my C# object null after I have instantiated it?
I either don't know how to instantiate a class in C#, or there is a trick with 2D matrices that I'm missing here. (Either way I'm new to it all, and I limit myself to asking one question on Stack Overflow per day, so go easy with the downvotes...)
My program is a Win8 app.
I have a C# class with three members. They are:
class CMyClass
{
public double[][] matrix1;
public double[][] matrix2;
public double[][] matrix3;
}
And I try to instantiate it in my program like this:
CMyClass myObject = new CMyClass();
Then if I try to access any of the matrix members to read or write to the arrays I get a null reference exception error that say the object isn't instantiated. Is something missing from my class or is the problem with the way I try to instantiate the object?
Because you haven't instantiated those items yet.
class CMyClass
{
public double[][] matrix1;
public double[][] matrix2;
public double[][] matrix3;
public CMyClass()
{
matrix1 = new double[][] {};
matrix2 = new double[][] {};
matrix3 = new double[][] {};
}
}
Creating an instance of an object initializes its members to their default values. For reference types (like an array) this means null.
You need to explicitly create an empty array of the size you want in the objects constructor;
matrix1 = new double[4][2];
you can also put it in the declaration of the member (but that would be odd since you probagbly dont know what size you want - or maybe you do)
You have only instantiated the CMyClass, you haven't instantiated any of the members of the class.
Try adding a default constructor to the class, and in the constructor set the member values.
public CMyClass()
{
matrix1 = new double[][] {};
...
}
Just tried with tiny console app.
static void Main(string[] args) {
CMyClass myObject = new CMyClass();
myObject.matrix1= new double[1][] ;
myObject.matrix1[0] = new double[1];
Console.WriteLine(myObject.matrix1[0][0]);
}
Thanks folks. This seems to be the best working solution for me:
> class CMyClass
> {
> public double[][] matrix1;
>
> public CMyClass(int x)
> {
> matrix1 = new double[x][];
> for (int i = 0; i < x; i++)
> { matrix1[i] = new double[x]; }
> }
> }
Then in program:
int matrixSize = 10;
CMyClass MyNewObject = new CMyClass(matrixSize);
Now I can read and write to the elements of the matrix.
Solved! =D

Adding CustomClassObjects to Dictionary as values

I have a task where I need to have two values for one key in Dictionary.
Solution found in web is to make new class with two fields and use it's objects as values.
But how can I assign value to my CustomClassObjects from Dictionary's for loop?
Here is the code:
Dictionary<char, Huffmans> HuffmanDictionary = new Dictionary<char, Huffmans>();
Program.text = File.ReadAllText(Program.sourcetext);
char character;
for (int i = 0; i < Program.text.Length; i++)
{
counter++;
character = Convert.ToChar(Program.text[i]);
if (HuffmanDictionary.ContainsKey(character))
HuffmanDictionary[character].probability++;
else
HuffmanDictionary.Add(character, 1);// here is the problem, obviously program can't assign value directly to class...
}
public class Huffmans
{
public int code = 0;
public double probability = 0;
}
Basically, I need to assign only "probability" values on this step. Should I call constructor for "Huffmans " on each iteration?
Big thanks for any help, Alex
You need to instantiate your class before adding the value:
HuffmanDictionary.Add(character, 1);
Should be:
HuffmanDictionary.Add(character, new Huffmans{ code = 1 });
Alternatively you can create a constructor for your class:
public class Huffmans
{
public Huffmans(int _code)
{
code = _code;
}
public int code = 0;
public double probability = 0;
}
then you can do:
HuffmanDictionary.Add(character, new Huffmans(1));
EDIT:
Some more clarification:
HuffmanDictionary.Add(character, 1);
fails because you are passing a type int into the dictionary but it is expecting the type Huffmans. Our dictionary is : Dictionary<char,Huffmans>()
HuffmanDictionary.Add(character, new Huffmans{ code = 1 });
works because now we are creating a new object of type Huffmans and we are setting the code value to 1.
Not sure if I understood your comment correctly, but effectively we are doing the same as:
var newHuffmans = new Huffmans{ code = 1 };
HuffmanDictionary.Add(character, newHuffmans);
But rather than writing out all that code and creating a named variable with our class, we skip this and pass it directly into the dictionary.

Having two param lists with same size

The method PrintTimes(string a, int b) prints the string a, b times (i.e. PrintTimes("test",3) will print testtesttest).
I want to create a method, which will get a params array of strings and a params array of integers. So the call function will ook like this
PrintTimes("A","B","C","D",2,1,3,2);
Or
PrintTimes("A",2,"B",1,"C",3,"D",2)
Both of which will print AABCCCDD
Since there can be only one params parameter in a method, this is impossible. So is there a way to do this?
I know I can create a Class with a string and an int variable, and create a params array for the class. But I'd rather not, since it would involve constructing a new Class for each set
Why not using a class
public class PrintParameter
{
public int Count {get;set;}
public string Content{get;set;}
}
Then
public void PrintTimes(List<PrintParameter> inputs)
{
//for each input print the "Content", "Count" times
}
Or
public void PrintTimes(params PrintParameter[] inputs)
{
//for each input print the "Content", "Count" times
}
If you don't want to define a class you may try something like List<KeyValuePair<string,int>> or other alternatives such as List<Tuple<string,int>> and etc. However the preferred way of doing is to use a class with meaningful properties.
How about just dropping the params keyword and taking arrays instead? That is, make the signature PrintTimes(string[], int[]). PrintTimes(new[]{"A","B","C","D"}, new[]{2,1,3,2}); isn't that much more to write.
There are several ways you can go about solving this problem. While you can only have one params, you can just make both your parameters arrays:
PrintTimes(string[] strings, int[] printCounts)
{
// Assert strings.Length == printCounts.Length
for (int i = 0; i < strings.Length; i++)
{
for (int j = 0; j < printCounts[i]; j++)
{
// Print strings[i]
}
}
}
Then it can be called like this:
int[] numbers = new int[3] {1, 2, 3};
string[] names = new string[3] {"Matt", "Joanne", "Robert"};
PrintTimes(names, numbers);
Following up on Hossein's suggestion, why not something as simple as:
void PrintTimes(List<String> strings, List<Int> count)
(or do it as an array as the comments said) Then inside PrintTimes require the inputs to be the same length or some logical fail when they don't.

c# Confusion over what type of array and usage

I am new to c# and am trying to build an array of arrays of items. I have looked at 2d arrays and jagged arrays and simply can't work out what i'm supposed to be using and can not get it to work. It's not so much building the array it's then looping through it to interrogate the array elements. I'm working within an existing library which is where all the variables come from, most of the other supporting code I've left out as it's not relevant. Once a instance is found i'm then trying to update a field from 0 to 1. Many thanks for any help in advance.
//Declare array
private double[,] myOpenTrades;
private void mymethod (double score, double RSIComboScore, int type, int line)
{
myOpenTrades[line,0] = type;
myOpenTrades[line,1] = CurrentBar;
myOpenTrades[line,2] = Close[0];
myOpenTrades[line,3] = rewardClose;
myOpenTrades[line,4] = riskClose;
myOpenTrades[line,5] = score;
myOpenTrades[line,6] = RSIComboScore;
myOpenTrades[line,7] = this.getSMATrend();
myOpenTrades[line,8] = Math.Round(NSRSICS(5, 15, 60, 240).Rsi200AVGPlot[0]);
myOpenTrades[line,9] = myReward;
myOpenTrades[line,10] = myRisk;
myOpenTrades[line,11] = 0;
}
protected override void OnMyChange()
{
foreach(double[] row in myOpenTrades)
{
if(Close[0] >= row[3] && row[11]==0)
{
Print("WIN:"+row[10]);
row[11]=1;
}
else if(Close[0] >= row[4] && row[11]==0)
{
Print("LOSE:"+row[9]);
row[11]=1;
}
}
{
I don't know why this is being downvoted, it seems like a legitimate question from a new user who made some effort.
To answer your question, an array of arrays is not the best choice, because from a logical organization perspective you don't have a "grid" (i.e. 2D array) of the same item, you have multiple items as one record, and an array of records. Not to mention that you appear to be trying to mix and match types; your array is declared as double but the first record type is an integer.
I would recommend using a class as follows:
class OpenTrades
{
public int Type;
public Bar CurrentBar;
public double Score;
// etc...
}
(This is assume that CurrentBar's type is Bar; you'll have to substitute Bar with whatever that type actually is.)
Then you would instantiate an array of your class like this:
OpenTrades[] myOpenTrades = new OpenTrades[11]; // This will create an array of 11 elements, indices 0 to 10
Now in your mymethod function you can assign values to each of your members.
myOpenTrades[line].Type = type;
myOpenTrades[line].Bar = CurrentBar;
myOpenTrades[line].Score = score;
// etc ...

Categories