Value inside a list gets changed on modification C# - c#

Currently I have a class called Field:
public class Field
{
public int Id { get; set; }
}
var listOfListOfFields = new List<List<Field>>();
var listOfFields = new List<Field>(){ new Field {id = 1}}; // in reality, data comes here.
for (int i = 0; i <= 2; i++)
{
var copyFirstList = listOfFields.ToList(); // to avoid reference thing, I still get same value
for(int j =0; j < copyFirstList.Count; j++)
{
copyFirstList[j].Id = i;
}
listOfListOfFields.Add(copyFirstList);
}
The output in the listOfListOfFields contains 2 for all the lists in id. Please suggest.

Copying a list of references types gives you the same references to those reference types (nothing changed). For instance, if someone gave you a bucket of post-it-notes with phone numbers on them, and you tip them in to another bucket, you still have the same post-it-notes!
There are many ways to solve this problem. However, one way is to project using Select and recreating the objects
copyFirstList = listOfFields.Select(x => new Field() {Id = x.Id}).ToList():

Related

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.

c# Array returning all elements as null

I have a getter that reads an existing array from another Property of that class and filters out elements with specific Properties.
The problem is, that after reading the Property it returns an array with the correct number of elements but all the containing elements are null.
During debugging I saw that the elements have been inserted correctly.
public Member[] Assigned_Users {
get {
Member[] _assigned_users = new Member[0];
//ERROR: foreach gets an array with the correct length, but all null elements
foreach (Member m in Nested_Users) {
if (m.Typ != Member.typ.User) continue;
Member[] _tmp = new Member[_assigned_users.Length + 1];
for (int r = 0; r <= _nested_members.Length - 1; r++) {
_tmp[r] = _assigned_users[r];
}
_tmp[_assigned_users.Length] = m;
_nested_members = _tmp;
}
foreach (Member m in Members) {
if (m.Typ != Member.typ.User) continue;
Member[] _tmp = new Member[_assigned_users.Length + 1];
for (int r = 0; r <= _nested_members.Length - 1; r++) {
_tmp[r] = _assigned_users[r];
}
_tmp[_assigned_users.Length] = m;
_nested_members = _tmp;
}
return _assigned_users;
}
}
public Member[] Nested_Users {
get {
Member[] _nested_users = new Member[0];
foreach (Member m in Nested_Members) {
if (m.Typ != Member.typ.User) continue;
Member[] _tmp = new Member[_nested_users.Length + 1];
for (int i = 0; i < _nested_users.Length - 1; i++) {
_tmp[i] = _nested_users[i];
}
_tmp[_nested_users.Length] = m;
_nested_users = _tmp;
}
//creates and returns a correct aray, acording to the debugger
return _nested_users;
}
}
Any Ideas how to fix this?
EDIT:
This code serves the following Purpose.
In the very ancient days of our company, a lot or LDAP groups existed. As many LDAP implementations don't allow to read all the users from a nested LDAP group, my company build their own User management back-end. This is one part of it.
If a group has a another group assigned (these infos are all stored in an SQL database) It should read the nested groups members and Assign them DIRECTLY to base group.
All of this is just done for services that authenticate against LDAP but don't know how to read users of a Nested group.
But even if List<Member> would be the better way to go, as suggested in the comments (and known by be), there should be no reason why the array is filled with null instead of Member objects. Or am I missing something here?

Updating a list within a list<class>

Since having a list<list<>> is bad practice, i have created a class containing 2 lists:
public class TouchSet
{
public List<DateTime> timeList = new List<DateTime>(ammountOfXValues);
public List<int> touchList = new List<int>(ammountOfXValues);
}
Then i have a function that is used to initialize the entire thing so i can use it further down the road:
public void initializeTouchDataListObject()
{
touchSetList = new List<DataStructure.TouchSet>(DataStructure.maxButtonsActive);
List<int> tempTouchList = new List<int>();
List<DateTime> tempTimeList = new List<DateTime>();
for (int a = 0; a < DataStructure.maxButtonsActive; a++)
{
DataStructure.TouchSet tempTouchSet = new DataStructure.TouchSet();
tempTouchSet.timeList = tempTimeList;
tempTouchSet.touchList = tempTouchList;
touchSetList.Add(tempTouchSet);
}
}
This is the loop where i add values to the list:
for (int i = 0; i < DataStructure.maxButtonsActive; i++)
{
if(touchSetList[i].timeList.Count == DataStructure.ammountOfXValues)
{
//RemoveAt removes at the given index within a list
touchSetList[i].timeList.RemoveAt(0);
touchSetList[i].touchList.RemoveAt(0);
//add
touchSetList[i].timeList.Add(DateTime.Now);
touchSetList[i].touchList.Add(temp);
}
else if(touchSetList[i].timeList.Count < DataStructure.ammountOfXValues)
{
//add
touchSetList[i].timeList.Add(DateTime.Now);
touchSetList[i].touchList.Add(temp);
}
else
{
int overLength = touchSetList[i].timeList.Count - DataStructure.ammountOfXValues;
//remove
touchSetList[i].timeList.RemoveRange(0, overLength + 1);
touchSetList[i].touchList.RemoveRange(0, overLength + 1);
//add
touchSetList[i].timeList.Add(DateTime.Now);
touchSetList[i].touchList.Add(temp);
}
}
The issue I'm facing is, that within a single pass through the for loop , it adds temp to every touchList not just the touchList of touchSetList[i].
For example after adding temp to touchSetList[i].touchList every other touchList also contains temp, not just the one where the index i applies to the class within the list.
I'm not sure why the List is behaving this way, and why it adds the value to every list not just the one with the corresponding index. I was under the impression that you can use an index to access a single item within a list. Any pointers or advice is appreciated.
public void initializeTouchDataListObject()
{
touchSetList = new List<DataStructure.TouchSet>(DataStructure.maxButtonsActive);
for (int a = 0; a < DataStructure.maxButtonsActive; a++)
{
List<DateTime> tempTimeList = new List<DateTime>();
List<int> tempTouchList = new List<int>();
DataStructure.TouchSet tempTouchSet = new DataStructure.TouchSet();
tempTouchSet.timeList = tempTimeList;
tempTouchSet.touchList = tempTouchList;
touchSetList.Add(tempTouchSet);
}
}
You don't create a new tempTimeList and tempTouchList for every new tempTouchSet, so they all get passed pointers to THE SAME list.
Do the initialization for tempTimeList and tempTouchList within your loop and you get a new one for every tempTouchSet.
Actually I'd redesign the entire thing. What I read from your code is that you want to store the timestamp of a touch event together with some information about the touch event.
So I'd design a class that contains all that data:
public class TouchInfo
{
public DateTime touchTime;
public int touchEvent;
}
Then you can easily store one list of touch events, instead having to keep two lists in sync.
List<TouchInfo> touchEvents = new List<TouchInfo>();
public void initializeTouchDataListObject()
{
for (int a = 0; a < DataStructure.maxButtonsActive; a++)
{
touchEvents.add(new TouchInfo());
}
}
In your initializeTouchDataListObject() method, you create tempTouchList and tempTimeList. Then, for EVERY TouchSet, you add these lists as their timeList and touchList. The problem here is that the two created lists are passed by REFERENCE, meaning that every single TouchSet has a reference to the two exact same lists. They all share the same lists and thus lists are changed for every TouchSet in every iteration.
You have 3 conditions. Add(temp) is in all 3.
1) a < b
2) a = b
3) a > c
​

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++)

Changing one element of an array changes others

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

Categories

Resources