This question already has answers here:
C# Copy Array by Value
(8 answers)
Copy one 2D array to another 2D array
(4 answers)
Closed 2 years ago.
This is an addendum to a previous question I asked about copying classes.
The basic answer to the previous question (copying classes not as reference type) was to use a memberwise clone method to avoid keeping links between the two classes.
Doing this on a class with only int values works, but this breaks apart as soon as I introduce arrays in the mix. See the script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class MyClass
{
public int[] myNumber;
public MyClass ShallowCopy()
{
return (MyClass)this.MemberwiseClone();
}
}
public class Test : MonoBehaviour
{
Dictionary<string, MyClass> myDictionary1 = new Dictionary<string, MyClass>();
Dictionary<string, MyClass> myDictionary2 = new Dictionary<string, MyClass>();
void Start()
{
myDictionary1.Add("a", new MyClass() { myNumber = new int[] { 1, 1 } });
myDictionary1.Add("b", new MyClass() { myNumber = new int[] { 2, 2 } });
myDictionary2["b"] = myDictionary1["a"].ShallowCopy();
myDictionary2["b"].myNumber[0] = 3;
Debug.Log(myDictionary1["a"].myNumber[0]); //output 3, I'd want it to still be 1
}
}
I've tried implementing the ShallowCopy method (implemented in line 9 and used in line 25) and it doesn't work. I should implement a DeepCopy method, but I don't know how to formulate it applied to arrays.
My new DeepCopy function would be something like
public MyClass DeepCopy()
{
MyClass other = (MyClass)this.MemberwiseClone();
other.myNumber = ?????????????????????? //int[] deep copy
return other;
}
But I have no idea how to formulate a copy of the array. I've found a similar thread dealing with this, but I couldn't adapt the solution to my case.
Thanks in advance!
If you know that your array is going to be full of value types like int, or you have reference types and you want both arrays to refer to the same instance, you can use CopyTo
int[] copyTarget = new int[copyFrom.length];
copyFrom.CopyTo(copyTarget, 0);
If your array can/does have reference types in it, and you don't want the new array to reference the same instances, you will have to instead move through the elements doing a memberwise clone of each:
int[] copyTarget = new int[copyFrom.length];
for(int i = 0; i < copyTarget.Length; i++)
{
copyTarget[i] = copyFrom[i].MemberwiseClone();
}
Related
This question already has answers here:
How do I clone a generic list in C#?
(29 answers)
C# Value and Reference types
(6 answers)
Closed 4 years ago.
class ListHolder
{
public List<char> List;
public ListHolder(List<char> l)
{
this.List = l;
}
}
class Program
{
static void Main(string[] args)
{
List<char> a = new List<char>();
a.Add('s');
ListHolder c = new ListHolder(a);
a.Clear();
Console.WriteLine(c.List.Count);
}
}
I've put some list into that class, than I cleared the list and wrote the count of the list in the class... I would expect that the output should be "1" (as the list in the class contains the letter 's') but instead it writes "0". How is possible, that a.Clear clears even the list in the class? How can I achieve clearing only the list in the Main and the list in the class letting be?
Since you are passing a reference instead of the list itself, you will get 0 after clearing your list.
What you have to do is passing to the class a new List containing the other list's values:
cl c = new cl(new List<char>(a));
This way, even if you clear the 'main' list, in your class you'll have 1 as items count.
Hope this helps.
List and other classes are reference types. In few words, it means you have an object somewhere in memory and a reference(s) on it.
this.l = l; means you copied the reference to the first list to the class field. So you have one list and two references on it. And when you clear the list via a variable, no matter how you address it after clearing - via a or cl.l. Your single list is cleared already.
If you want to avoid this, you need to create a copy of list in your constructor:
public cl(List<char> l)
{
this.l = new List<char>();
this.l.AddRange(l);
}
}
I recommend you to read more information about reference types. They are used widely and knowledge about them will give you a good base for programming skills.
if (a is System.ValueType)
{
//never
Console.WriteLine("List is value type");
}
if ('s' is System.ValueType)
{
//always
Console.WriteLine("char is value type");
}
I think you know, char is value type, but list is reference type.
Even code like this; it would be same.
List<char> a = new List<char>();
a.Add('s');
List<char> c = a;
a.Clear();
Console.WriteLine(c.Count);
This question already has answers here:
What is a NullReferenceException, and how do I fix it?
(27 answers)
Closed 4 years ago.
I was learning how to use Json to save data into files when a continuous error was appearing, its "Nullreference, object reference not set to an instance of an object" and I started to think that I was doing the save file part right but the error was in my usage of arrays somehow, so I started a new project and I started using arrays the same way without any usage of Json, and indeed the error was there, so I know there is something wrong with this but I cant really tell what, I know how simple arrays are initialized and how every array has to be initialized before being used, but in this case something is wrong for some reason, can you tell me what is that?
The scenario is really simple as its new project only to test the arrays the way I was using them in my bigger project, so its mainly a GameClass that hold several hi-scores tables (an array of them), these tables are made by a class (HiScoreClass) that holds arrays of names and points, and then well I was just initializing this and the error appeared, so no need to dig further, can you tell me what is wrong here? thanks a lot for your help, Im totally lost in this point. (To test this in a project I just attached the code to the camera so its nothing else in scene to think other object could be causing it)
using UnityEngine;
using System.Collections;
public class embed : MonoBehaviour
{
GameClass myGame;
int i, j;
void Awake ()
{
myGame = new GameClass();
myGame.arrptnm = new HiScoreClass[10];
for (i = 0; i < 100; i++)
{
myGame.arrptnm[i].pts = new int[10];
myGame.arrptnm[i].names = new string[10];
for (j = 0; j < 10; j++)
{
myGame.arrptnm[i].pts[j] = i * j;
myGame.arrptnm[i].names[j] = "ASD";
}
}
}
void Update ()
{
}
}
[System.Serializable]
class GameClass
{
[SerializeField]
public HiScoreClass[] arrptnm;
}
[System.Serializable]
class HiScoreClass
{
[SerializeField]
public int[] pts;
public string[] names;
}
The problem is that you're defining an array of HiScoreClass objects, but you're not initializing the elements in that array to new instances of the HiScoreClass class. Then you get a NullReferenceException when you try to reference a property of an item in the array, like myGame.arrptnm[i].pts.
To solve this, you can initialize each item to a new instance when you do your first iteration (also change the 100 to 10, since that's the size we declared for this array):
for (int i = 0; i < 10; i++)
{
// Initialize our array items
myGame.arrptnm[i] = new HiScoreClass();
// rest of code omitted...
This question already has answers here:
Adding values to a C# array
(26 answers)
Add new item in existing array in c#.net
(20 answers)
Closed 5 years ago.
I need to add values to my array one integer value at a time, via user input.
I don't know how to ask it more clearly, but my goal is to define an integer array in Main(), then pass it to Interactive() where a user is supposed to enter 20 different ints and the program should add them to the array.
It would be tedious to continue defining new arguments for each object (like this):
int One = ArrayOne[0]
int Two = ArrayOne[1]
int Three = ArrayOne[2]
because I am filling 20 array objects, surely there is an easier way?
Can someone help?
Here is the code I am working with:
class Program
{
static void Main(string[] args)
{
int[] intArray = new int[20];
}
public static int[] Interactive(int[] args)
{
int[] ArrayOne = new int[20];
Write("\n Write an integer >>");
ArrayOne[0] = Convert.ToInt32(ReadLine());
foreach (int x in ArrayOne)
{
if (x != ArrayOne[0])
Write("\n Write another integer");
ArrayOne[x] = Convert.ToInt32(ReadLine());
WriteLine("\n {0}", ArrayOne[x]);
}
ReadLine();
return ArrayOne;
}
}
Try using a List. Unlike arrays their size can be dynamically changed.
using System.Collections.Generic;
public class Example
{
public static void Main()
{
List<int> numbers = new List<int>();
numbers.add(1);
numbers.add(2);
}
}
Are you looking for this?
int[] intArray = Interactive(values here);
public static int[] Interactive(int[] args)
{
//TODO:
}
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
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 ...