Assume we have an array list of type Employe , does expanding it's length by 1 make a new object in the list ?
is the code in else statement correct? and is it recommended?
public void ModifierEmp(int c)
{
for(int i = 0; i < Ann.Count; i++)
{
if(Ann[i].Code == c)
{
Ann[i].saisie();
} else
{
i = Ann.Count + 1; //expanding arraylist ann
Ann[i].saisie(); //saisie a method for the user to input Employe infos
}
}
}
https://imgur.com/VfFHDKu "code snippet"
i = Ann.Count + 1;
The code above is not expanding the list: it is only setting your index variable (i) to have a new value.
If you wanted to make the list bigger, you would have to tell it which object to put into that new space you create. For example:
Ann.Add(anotherItem);
Of course, this gives you the ability to decide whether to add an existing item, create a new item (e.g. Ann.Add(new Something() { Code = c })), or even add a null value to the list (which is not usually a good idea).
Related
I've been trying to add multiple items to a list using a temporary variable and a loop of some kind. I'll create the temp variable and list outside of the loop, and then inside the loop the temp variable will change value, and then will be added to the list as a new element before the loop repeats. The problem is, whenever the temp variable is changed, all elements in the list will change to be the same.
As an example, if I was making a list of fruits, and entered te list 'banana', 'apple' and 'pear', the list when written to the console would read 'pear', 'pear' and 'pear', which is also how the list appears in debugging mode.
The specific code I've been typing is below:
string inputText = "";
List<TextNumbers> inputTextChars = new List<TextNumbers>();
TextNumbers temp = new TextNumbers();
bool charFound = false;
inputText = Console.ReadLine();
foreach (char letter in inputText)
{
for (int i = 0; i < inputTextChars.Count; i++)
{
if (letter == inputTextChars.ElementAt(i).character)
{
charFound = true;
}
}
if (charFound == false)
{
temp.character = letter;
temp.number = 0;
}
temp.number++;
inputTextChars.Add(temp);
charFound = false;
}
inputTextChars.Sort();
foreach (TextNumbers text in inputTextChars)
{
Console.WriteLine(text.character + ": " + text.number);
}
The class 'TextNumbers' is:
public class TextNumbers
{
public char character;
public int number;
}
So as you can see from the accepted answer on this question :
Yes, a list of reference types is actually just a list of references
This means you are adding a reference to temp to the list every time.
To avoid this, move the declaration of the temp variable to within your loop so that you are adding a reference to a completely new object every time, like so:
foreach (char letter in inputText)
{
TextNumbers temp = new TextNumbers();
//..... rest of code
I actually know the answer to the question (I think) but I don't know the reason...
So, I know that if I have a class like the following:
class Man
{
public string Name;
public int Height;
public Man() { }
public Man(string i_name, int i_height)
{
Name = i_name;
Height = i_height;
}
}
And I have the following Program class (with main function):
class Program
{
static void Main(string[] args)
{
Program p = new Program();
Man g = new Man("greg", 175);
//assigning null to g inside the function.
p.ChangeMan(g);
Console.WriteLine(g == null? "the function changed g out side the function" : "the function did not change g out side the function");
//the output of course is that the function did not change g outside the function.
//now I am creating a list of Man and adding 5 Man instances to it.
List<Man> manList = new List<Man>();
for (int i = 0; i < 5; i++)
{
manList.Add(new Man("Gadi" + i.ToString(), 10 * i));
}
//assigning null to the list insdie the function
p.ChangeList(manList);
Console.WriteLine(manList == null ? "the function changed the list out side the function" : "the function did not change the list out side the function");
//the output of cousre again is the function did not change the list out side the function
//now comes the part I dont understand...
p.ChangeManInAList(manList);
Console.WriteLine("list count = " + manList.Count());
//count is now 6.
Console.WriteLine(manList[0] == null ? "the function changed the element out side the function" : "the function did not change the element out side the function");
//the out again - the function did not change...
}
public void ChangeMan(Man g)
{
g = null;
}
public void ChangeManInAList(IList<Man> gadiList)
{
Man g = gadiList.First<Man>();
g = null;
Console.WriteLine(g == null? "g is null" : "g is not null");
gadiList.Add(new Man("a new gadi", 200));
Console.WriteLine("list count = " + gadiList.Count());
}
public void ChangeList(List<Man> list)
{
list = null;
}
}
I am assigning null to the first element of the list + adding one Man to the list. I expected that if I can add to the list, I can also change the elements, but I saw different...
I was able to add a Man to the list but could not assign null to one of the elements, how come? I know the list is passed by value so I can not change the list itself (like assigning null to it), but I can add to it? and can not assign null to the elements? are they being passed by val as well?
will be happy for some good and clear explanation :)
Here is your point of confusion:
Man g = gadiList.First<Man>();
g = null;
What you are essentially doing is getting a Man out of the list and assigning it to the local variable g.
Then, you assign a different value to the variable g.
At no point here did you change the value of any member of the list, you simply changed the value which the variable g refers to.
Let's try to compare it to this example:
int a = 5;
int b = a;
b = 3;
//you wouldn't expect `a` to be 3 now, would you?
In order to change the value of the list item, you would need to explicitly set the list index to a different value:
Man g = gadiList.First<Man>();
gadiList[gadiList.IndexOf(g)] = null;
//or specifically in this case:
gadiList[0] = null;
When you get element from list you get new reference to list item.
So as a result you get two references: one (private reference in list object), your reference.
When you set your reference to null it do not affect reference in list object. You reference became null, but private list reference remains the same.
So, I hope this is simple. I'm coming up with a way to store disconnected entities (due to my case being quite peculiar), and for it to work, I'd like to create a Dictionary with those values inside a for loop.
But I'm getting "An item with the same key" has been added problem, which I do not know why.
I've tried the following:
Dictionary<int, EntityState> StateProduct = new Dictionary<int, EntityState>();
for (int s = 0; s < userProducts.Count; s++ ) //userProducts.Count had value of 3
{
StateProduct.Add(s, EntityState.Modified);
}
But I get the error:
In which:
I really really do not know what's going on..
Edit: Here is the complete code
var dbIboID = dbs.OrderDB.Where(x => x.OrderID == Order[0].OrderID).FirstOrDefault();
if(dbIboID.IboID != uid)
{
return false;
}
//2nd Step:
//2.0 Attach it. Yes I know it sets it as unchanged. But let me do the magic trick!!!
dbIboID.OrderProcess = Order.ToList(); //CHANGED
dbs.OrderDB.Attach(dbIboID);
//2.1 Extract original values from the database.
var originalProducts = dbs.OrderProcessDB.Where(x => x.OrderProcessID == Order[0].OrderProcessID).ToList();
var userProducts = Order.ToList();
//This is a dictionary which will be used to set all other entities with their correct states!
Dictionary<int, System.Data.Entity.EntityState> StateProduct = new Dictionary<int, System.Data.Entity.EntityState>();
//2.3 Find new added products. addedProducts = userProducts[key] - originalProducts[key]
if(userProducts.Count > originalProducts.Count)
{
for (int i = originalProducts.Count - 1; i < userProducts.Count; i++ )
{
StateProduct.Add(i, System.Data.Entity.EntityState.Added);
}
}
//2.3 Find Deleted products = originalProducts - userProducts. Do reverse of the addedProducts
else
{
for (int i = userProducts.Count - 1; i < originalProducts.Count; i++)
{
StateProduct.Add(i, System.Data.Entity.EntityState.Deleted);
}
}
//2.4 Find modified products modifiedProducts = [userProducts - addedProducts] different originalProducts
//This is not 100% fool proof. Because there will be times that I will always have a modification,
// when objects remained unchanged.
for (int s = 0; s < userProducts.Count; s++ )
{
StateProduct.Add(s, System.Data.Entity.EntityState.Modified);
}
//2.5 Painting Process:
for (int i = 0; i < dbIboID.OrderProcess.Count(); i++ )
{
dbs.DB.Entry(dbIboID.OrderProcess[i]).State = StateProduct[i];
}
The code as you have shown it should not produce that exception, because the dictionary was allocated immediately prior to the loop, and thus should be empty, and the items being added all are unique integers.
My guess is that the dictionary already had some values in it. If so, then using Add to set a value will throw an ArgumentException, since the value corresponding to that key can only be replaced, not added, for the Dictionary class only allows one value per key.
So, if you expect the dictionary not to already have a value for a key, and want an error exception to be thrown if it does, do:
StateProduct.Add(s, EntityState.Modified)
If you want to add or replace a value, do:
StateProduct[s] = EntityState.Modified;
I have the following object array, created from a custom class Room. Before I add a new Room to the array I want to verify that the Roomname is not already in the array. Here is a sample of what I am trying:
private void btnAddRm_Click(object sender, EventArgs e)
{
Room[] roomArray = new Room[20];
test = txtName.text;
for (int i = 0; i < roomArray.length; i++)
{
if(test != roomArray[i].getRoomName())
{
addRoom();
}
}
}
GetRoomName() is the accessor that retrieves the RoomName from the class. I guess my question is why is this code not working?
Thank you
Your current code will add the room as soon as the room's name doesn't equal the new room.
Instead, first check that none of the rooms have the existing name and only then add it:
private void btnAddRm_Click(object sender, EventArgs e)
{
Room[] roomArray = new Room[20];
test = txtName.text;
bool exists = false;
for (int i = 0; i < roomArray.length; i++)
{
if (test == roomArray[i].getRoomName())
{
exists = true;
break;
}
}
if (!exists)
{
addRoom();
}
}
Your code fires addRoom() every time there is non-matching room in current array.
I think, you're looking for something like that:
if(!roomArray.Any(r => r.getRoomName() == test))
addRoom();
or using All method:
if(roomArray.All(r => r.getRoomName() != test))
addRoom();
You should finish looping through the entire array prior to adding the new room. With what you have if you have a new room name that doesn't match any existing rooms it'll call addRoom() 20 times.
Room[] roomArray = new Room[20];
test = txtName.text;
bool doesRoomExist = false;
for (int i = 0; i < roomArray.length; i++)
{
if (test == roomArray[i].getRoomName())
{
doesRoomExist = true;
break;
}
}
if (!doesRoomExist)
addRoom();
You can also condense you're for loop by using the Any extension method, you will need using System.Linq to do so.
if (!roomArray.Any(room => room.GetRoomName() == test))
addRoom();
Like others already stated your code does not make any sense. You create an array of rooms leaving all elements uninitialized (null). Then you check for existence of a room within that array. Also in your loop you "add" the new room each time an element has a different name. I have no clue how you want to add something to an array that is outside of the scope of your addRoom method. I hope this is not your actual code!
So first of all the room array should be created as a field of your class outside the scope of the btnAddRm_Click method.
Since you want to add rooms you should not use an array. Use a List<Room> instead. Otherwise you would need to know how many elements of your array are already initialized with a room. Also you would need to grow your array if the number exceeds the initial size of the array. This is exactly what List<Room> can do for you.
Your btnAddRm_Click event handler can then use LINQ to check for the existence of any room with the same name.
Please notice that you should use String.Compare(name1, name2) instead of name1 == name2.
private List<Room> _theRooms = new List<Room>();
private void btnAddRm_Click(object sender, EventArgs e)
{
if (!_theRooms.Any(r => string.Compare(r.Name, txtName.Text, StringComparison.CurrentCultureIgnoreCase) == 0))
{
addRoom();
}
}
Assuming that the room name is some kind of unique key for rooms you can also use a HashSet<Room> and then add the room anyway. HashSet will check for existence of the room. Your Room class however needs to overwrite Equals and GetHashCode then with Equals checking for equality of the room names.
I am trying to make a 1d array of lists. I make it like this:
public static List<string>[] words = new List<string>[30];
public static List<string>[] hints = new List<string>[30];
And I call it like this:
foreach (string item in vars.directory)
{
reader2 = new StreamReader(item);
while (reader2.Peek() > 0)
{
string line = reader2.ReadLine();
if (line.StartsWith("#"))
{
vars.words[counter].Add(line.Substring(1, line.Length - 1)); //here
}
else if (line.StartsWith("-"))
{
vars.hints[counter].Add(line.Substring(1, line.Length - 1)); //another here
}
else if (line == "#end")
{
counter++;
}
}
}
I just wanted to add that vars is where I keep my public variables and that counter is indeed at 0 when the loop starts.
EDIT
In my haste I forgot to add the question... oops...
Here it is: When I call the add function (or any another function for that matter) it returns a null reference exception. How can I fix this?
I assume you're crashing when attempting to call .Add on your array element. You need to initialize your arrays with valid objects.
for( Int32 i = 0; i < vars.words.Length; ++i )
vars.words[i] = new List<string>();
for( Int32 i = 0; i < vars.hints.Length; ++i )
vars.hints[i] = new List<string>();
Why not just make a List<List<string>>, but yes you can make an array of lists
Using a list of lists, as already recommended, would make you escape your problems,
and it´s much more flexible and handy than your construction.
-> f.i. if the size of your data changes, you don´t have to change the list size, but the array
Here's a one-liner to initialize an array of lists of size 30:
static List<string>[] lists = (from i in Enumerable.Range(0, 30)
select new List<string>()).ToArray();
The problem is that array values are initialized to the default value, and the default value for reference types is null.
default(List<string>) returns null.
So, you'll need to re-initialize the objects in the array before you can access them, otherwise you will get a NullReferenceException.
One way to initialize all the objects in your array up front is to use this Linq statement:
const int sizeOfLists = 5;
List<string>[] lists = Enumerable.Range(0, sizeOfLists)
.Select(i => new List<string>())
.ToArray();
Another option is to initialize and add the sub-lists only when you need them, by using an outer List:
var lists = new List<List<string>>();
// ...
var aSubList = new List<string>();
lists.Add(aSubList);
This is particularly useful if you don't know the size of the outer set of lists up-front, and is still accessible by index.
(This was a comment before, but I made it an answer since many other answers got caught up in the solution and don't describe the problem)
You could initialize the lists right before you use them:
foreach (string item in vars.directory)
{
reader2 = new StreamReader(item);
while (reader2.Peek() > 0)
{
string line = reader2.ReadLine();
// new code
if (vars.words[counter] == null) vars.words[counter] = new List<string>();
if (vars.hints[counter] == null) vars.hints[counter] = new List<string>();
if (line.StartsWith("#"))
{
vars.words[counter].Add(line.Substring(1, line.Length - 1)); //here
}
else if (line.StartsWith("-"))
{
vars.hints[counter].Add(line.Substring(1, line.Length - 1)); //another here
}
else if (line == "#end")
{
counter++;
}
}
}