Changing one element of an array changes others - c#

I have the following piece of code:
Chromosome[] pop = new Chromosome[popSize];
int[] initialGenes = new int[i];
for (int m = 0; m < i; m++)
initialGenes[m] = -1;
for (int j = 0; j < popSize; j++)
{
pop[j] = new Chromosome(graph, initialGenes);
}
Chromosome is my class and has a property
public int[] Genes { get; set; }
As you can see I initialize an array of Chromosome objects. The problem is when I try to change the value of pop[i].Genes[k] (e.g. pop[1].Genes[2] = 123) all Genes[k] of pop are changed (i.e.
pop[0].Genes[2] == 123
pop[2].Genes[2] == 123
etc.)
Could anyone explain what the problem is?
Thanks.

Change your constructor of Chromosome to make a copy of the array that is passed in.
I assume, your constructor looks like this:
public Chromosome(int[] initialGenes)
{
Genes = initialGenes;
}
But it should look like this:
public Chromosome(int[] initialGenes)
{
Genes = new int[initialGenes.Length];
Array.Copy(initialGenes, Genes, Genes.Length);
}

This happens because you pass same object to all Chromosome clases. You should create new copy of initialGenes for each Chromosome class

Related

How to read Object list item in C#

I have a object that prints a multidimensional matrix, e.g:
namespace example;
Public class Object()
{
int lines, cols;
int matrix[,];
public Object(int lines, int cols)
{
this.lines = lines;
this.cols = cols;
matrix = new int[lines,cols];
PrintMatrix()
}
public void PrintMatrix()
{
Random rand = new Random();
Console.WriteLine();
for(int i = 0; i < lines ;i++)
for(int j = 0, j < cols; j++)
matrix[i,j]= rand.nextInt(1,10);
Console.WriteLine(matrix[i,j));
}
}
i want to print in console output something like this:
matrix 1:
1 2 3
4 2 4
3 3 1
matrix 2:
2 3 4 4
1 1 2 2
3 3 4 4
1 1 8 8
matix 3:
...
So i have tried to insert the Object inside of List or Arraylist:
static void Main(string[] args)
{
List<Object> conteiner = new List<Object>();
Object foo = new Object(3,3);
Object anotherFoo = new Object(4,4);
conteiner.add(foo);
conteiner.add(anotherFoo);
foreach(object item in conteiner)
{
console.WriteLine(item)
}
}
it prints :
example.Object.foo;
example.Object.anotherFoo;
instead of multidimentional arrays.
What I´m doing wrong and how can i improve this solution?
If you want you could override the default ToString() method of your object.
public override string ToString()
{
return PrintMatrix();
}
Of course this forces you to make PrintMatrix() return a string but I would suggest to do it that way as it makes for better because more reusable code.
I would write something like the following :
public string PrintMatrix()
{
string result = string.Empty;
for(int i = 0; i < lines ;i++)
{
for(int j = 0, j < cols; j++)
{
matrix[i,j] = rand.Next(1,10);
result += $"{matrix[i,j]} ";
}
result += Environment.NewLine ;
}
return result;
}
By the way if you're wondering why your numbers are't random try creating only one Random object. You can then use it as you're doing now.
Cause you are printing the type itself which calls it's default ToString() instead you should do call PrintMatrix() on every object instance. As well consider giving a better name to your type than Object since that's a built-in type
foreach(Object item in conteiner)
{
item.PrintMatrix();
}

Using the value in one array to set the object in another

I am stuck trying to figure out how to use the values of one array of numbers to initialize a second array of objects. This might not be the most effective way to do something like this in a real program, but I am just trying to understand how to create a relationship between two different arrays.
The first array is just a randomly generated array holding values 0,1 or 2. The second array is an array of Occupant objects. Each occupant has an occupant id that will be either 0, 1 or 2. I am trying to generate the second array of occupants by copying the values of first array and then initializing the second based on the occupant id.
Nothing I have tried will compile, and I can't think of anything else on my own except writing a million if statements. Surely there must be a simple solution I am missing. Any help you can offer will be greatly appreciated.
FYI: Occupant is the base class, three classes derive from it, each with a unique id number.
static public class Board
{
static public Occupant[,] board = BoardGen();
static private Occupant[,] BoardGen()
{
Random myRandom = new Random();
int[,] setup = new int[10, 10];
for (int i = 0; i < setup.GetLength(0); i++)
{
for (int j = 0; j < setup.GetLength(1); j++)
setup[i, j] = myRandom.Next(0, 3);
}
Occupant[,] populate = new Occupant[10,10];
// How to link setup to populate using the number to choose an occupant based on it's id number?
return populate;
}
}
}
I would suggest to fill-in the second table along with the first, or even better, completely forget about the first table:
static private Occupant[,] BoardGen()
{
Random myRandom = new Random();
// Not needed
// int[,] setup = new int[10, 10];
Occupant[,] populate = new Occupant[10, 10];
for (int i = 0; i < populate .GetLength(0); i++)
{
for (int j = 0; j < populate .GetLength(1); j++)
{
int randomSetup = myRandom.Next(0, 3);
switch (randomSetup)
{
case 0:
populate[i, j] = new Occupant_0(); // Derived Class with id=0
break;
case 1:
populate[i, j] = new Occupant_1(); // Derived Class with id=1
break;
case 2:
populate[i, j] = new Occupant_2(); // Derived Class with id=2
break;
default:
break;
}
}
}
return populate;
}
abstract class Master
{
public abstract int Id { get; }
}
class A : Master
{
public override int Id => 1;
}
class B : Master
{
public override int Id => 2;
}
class C : Master
{
public override int Id => 3;
}
Type[] types = new Type[] { typeof(A), typeof(B), typeof(C) };
int[] yourIds = new int[100];
Master[] generated = new Master[yourIds.Length];
for (int i = 0; i < yourIds.Length; i++)
{
generated[i] = (Master)Activator.CreateInstance(types[yourIds[i] - 1]);
}
I cannot understand your question completely, but this logic should fit your situation.
The point is that you can create an instance in runtime with the System.Activator and a System.Type.

How can I add objects Cbook to my class CBooks without using lists

Cbooks has an atribute "CTeam[] Teams" and it is of fixed size (8). If I want to add objects to it using this in the Main:
CBook A1 = new CBook("Title1", "Author1");
CBook A2 = new CBook("Title1", "Author2");
CBooks ArrayOfBooks = new CBooks(8);
ArrayOfBooks.Add(A1);
ArrayOfBooks.Add(A2);
then position 0 and 1 are ocuppied, and the positions from 2 to 7 are null. What I want to do is, using a variable "int aux=0", count the ocupied positions like this:
for (int k = 0; k < NumberOfTeams; k++)
{
if (Teams[k].Name=="")
Aux += 1;
}
So, Aux in this case would be 2, then I want to do "Teams[Aux] = A" so that A would be in the position 2 and now I should have three objects in my array. But I'm getting "Index out of bound"
Your implementation then should look similar to this:
public class Program
{
public static void Main(string[] args)
{
Element a = new Element("A");
Element b = new Element("B");
MyArray array = new MyArray(8);
array.Add(a);
array.Add(b);
Console.WriteLine(array.Count()); //2 Elements are in the array
}
}
//Sample element class.
public class Element{
public readonly String MyString;
public Element(String myString){
MyString = myString;
}
}
//Sample array class.
public class MyArray{
private readonly Element[] myArray;
private int count; //Use a property here
public MyArray(int size){
//Be careful -> check if size is >= 0.
myArray = new Element[size];
}
public bool Add(Element element){
if(myArray.Length == count) // return false if no more elements fit.
return false;
myArray[count] = element;
count++;
return true;
}
public int Count(){
return count;
}
}
So there is no need for creating an extra count loop. Your "count" variable in "MyArray" class holds always the correct value.
Anyway the implementation or use case of this code is a little bit clunky.
Why are you cant use directly a more safe list or something. That would be a better solution.
What do you need CBooks for? From what I understand, it's just an array of 8 CBook objects so why not use CBook[]?
CBook A1 = new CBook("Title1", "Author1");
CBook A2 = new CBook("Title1", "Author2");
CBooks[] ArrayOfBooks = new CBook[8];
ArrayOfBooks[0] = A1;
ArrayOfBooks[1] = A2;
int aux = 0;
for (int k = 0; k < ArrayOfBooks.Length; k++)
{
//break the loop because we know there are no more books
if (ArrayOfBooks[k] == null)
break;
aux++;
}
The question doesn't cover what the variables NumberOfTeams and Teams are for but could those be added to the implementation of CBook?

Unit testing with NUnit. Null object error

I keep getting a null object reference error when im running one of my unit test.
Unit Test:
[Test]
public void EnumeratedData_ValidInputType_NoErrorAdded()
{
List<String> errorMessageList = new List<string>();
UserInputEntity myEntity = new UserInputEntity();
myEntity.DataTypes = new List<string>();
myEntity.DataTypes.Add("DateTime");
myEntity.DataTypes.Add("datetime");
myEntity.DataTypes.Add("decimal");
myEntity.DataTypes.Add("decIMAL");
myEntity.DataTypes.Add("DOUble");
myEntity.DataTypes.Add("double");
myEntity.DataTypes.Add("FLOat");
myEntity.DataTypes.Add("float");
myEntity.DataTypes.Add("INT");
myEntity.DataTypes.Add("int");
PathReader reader = new PathReader();
IOManager manager = new IOManager(reader);
VerificationManager testObject = new VerificationManager(manager);
testObject.EnumeratedDataTypes(myEntity, errorMessageList);
Assert.AreEqual(errorMessageList.Count, 0);
}
Method Code:
public void EnumeratedDataTypes(UserInputEntity inputs, List<String> errorMessageList)
{
inputs.EnumeratedDataTypes = new int[inputs.DataTypes.Count];
try
{
for (int i = 0; i < inputs.DataTypes.Count; i++)
{
inputs.EnumeratedDataTypes[i] = (int)Enum.Parse(typeof(Enumerations.ColumnDataTypes), inputs.DataTypes[i].ToUpper());
}
}
catch (Exception ex)
{
errorMessageList.Add(ex.Message);
}
}
Enum:
class Enumerations
{
public enum ColumnDataTypes
{
DATETIME = 0,
DECIMAL = 1,
DOUBLE = 2,
FLOAT = 3,
INT = 4
}
}
ErrorMessage:
FrazerMann.CsvImporter.Entity.Test.EntityVerificationTests.EnumeratedData_ValidInputType_NoErrorAdded:
System.NullReferenceException : Object reference not set to an instance of an object.
Im assumin im overlooking something stupidly simple but i cant see it. id appreciate it if someone could put me out of my misery.
In your EnumeratedDataTypes method, you first set the length of the inputs.EnumeratedDataTypes property to inputs.ColumnNames.Count, which is equal to 0 since it has not been filled with data yet (it is only the List capacity that has been set to 9).
Next, when filling this array property with data you loop from 0 to index (including) inputs.DataTypes.Count:
for (int i = 0; i <= inputs.DataTypes.Count; i++)
I count the size of the input.DataTypes list to 10. Thus, you will try to write data to an empty array.
I propose the following changes:
First, initialize the inputs.EnumeratedDataTypes array as follows:
inputs.EnumeratedDataTypes = new int[inputs.DataTypes.Count];
Second, use < instead of <= in the for loop:
for (int i = 0; i < inputs.DataTypes.Count; i++)

Dynamic Initialize in c#

I've a class
class sampleClass
{
...........
...........
public sampleClass()
{.........}
}
and in another class i created an array like
sampleClass[] X=new sampleClass[]{new sampleClass(),new sampleClass()}
here i gave 2 instance of the constructor. i need this dynamically..
that is the size of the array should be dynamically changed
It sounds like you want something like:
int size = // whatever
SampleClass[] array = new SampleClass[size];
for (int i = 0; i < size; i++)
{
array[i] = new SampleClass();
}
EDIT: If you really want to avoid a for loop, you could do something like:
SampleClass[] array = Enumerable.Range(0, size)
.Select(x => new SampleClass())
.ToArray();
... but I don't think that's actually better than using a loop.
This is just a syntactic sugar, you can gain the same using your own code:
sampleClass[] X = new sampleClass[num];
for(int i = 0; i < num; i++)
{
X[i] = new sampleClass();
}
You can initialize the array using a loop:
sampleClass[] X = new sampleClass[123];
for (int i = 0; i < X.Length; ++i)
X[i] = new sampleClass();
If your class was a value type the array is initialized when it is allocated:
struct sampleStruct { ... }
sampleStruct[] X = new sampleStruct[123];
// No need to initialize every array cell.
However, using a struct instead of a class is not something you should do simply to avoid a loop. You can read more about value types on MSDN.

Categories

Resources