Lists repeating last item added

3

I was studying about the lists in C # and I could not understand what's wrong with my code (it's probably going to be pretty basic), all items are the same as the last item added. I've simplified the code to focus on just that part of the error, am I doing something wrong? For what I saw to add, just use List.Add() , but it is not working. There is also another class in the project, the Itens class, which has the variable nomes used in the code (and only this variable).

I left all the code in Main() to get smaller.

class Program
{
    static void Main(string[] args)
    {
        Itens itens = new Itens();
        List<Itens> list = new List<Itens>();

        itens.nome = "GPU";
        list.Add(itens);

        itens.nome = "Livro";
        list.Add(itens);

        for (int i = 0; i < list.Count; i++)
        {
            Console.WriteLine("Item: " + list[i].nome);
            //Aqui ele imprime tudo igual a ultima string adicionada
        }
        Console.ReadLine();
    }
}
    
asked by anonymous 09.10.2017 / 15:47

3 answers

5

How about doing this?

using static System.Console;
using System.Collections.Generic;

public class Program {
    public static void Main(string[] args) {
        var list = new List<Item>() {
            new Item() { Nome = "GPU" },
            new Item() { Nome = "Livro" }
        };
        list.Add(new Item() { Nome = "Cadeira" });
        var item = new Item() { Nome = "Abóbora" };
        list.Add(item);
        var carro = new Item() { Nome = "Carro" };
        list.Add(carro);
        item = new Item() { Nome = "Outro objeto" };
        list.Add(item);
        list.Add(carro);
        for (int i = 0; i < list.Count; i++) {
            WriteLine($"Item: {list[i].Nome}");
        }
    }
}

public class Item {
    public string Nome;
}

See running on .NET Fiddle . And in Coding Ground . Also put it in GitHub for future reference .

I was not adding items differently, I was adding the same item so I only got the last value. You must create a new item to add to the list. When did:

itens.nome = "Livro";

I was changing the value of the same object created before, so the previous item pointed to this same object, but now with a new value.

This runs because the classes are types by reference, so what they have in the variable is a pointer to the object elsewhere. It looks like two things, but it's the same. If it were a struct then it would be different, so if it was an integer it would not happen. Read more at What's the difference between Struct and Class? .

Notice that I have come up with new ways of writing this. When you create the list you can already create the inline items and make the list start already with the items.

Then I added a new item by creating it inline again, ie you do not need to create a variable for it. You do not even need to assign values to your members after the object has been created.

But I also made the creation of the variable if it is important. Again, you have to create a new object.

Let's say I wanted another variable that holds an object and add a reference to this object in the list, I did this with carro .

Finally I created a new item in the same variable. Of course the variable loses the reference to the previous object, but I have shown that the important thing is to create the new object, not the variable.

I've still added the carro variable again, even without moving anything in the object. It is the same object being added, it is not another. If you move this object, the two entries in the list will be affected because they refer to the same object.

If you know the C pointers, this is it. Types by reference are always pointers to objects. Types by value are the objects themselves. In C # this becomes more abstract, but the internal mechanism is equal to C.

Then note that your itens is not an object, it is a variable that has a value, in this case a pointer, the object is not in items. It is a common mistake for people to think that variables always hold objects. This is only true for types by value.

I've changed the name of the class that makes the most sense, it's just an item, the list is several items.

    
09.10.2017 / 16:00
2

It's like Felipe Avelar , you're just changing a property of the object itens and inserting it several times; you would need to insert a different object for each position:

class Program
{
    static void Main(string[] args)
    {
        List<Itens> list = new List<Itens>();

        Itens itensGpu = new Itens();
        itens.nome = "GPU";
        list.Add(itensGpu);

        Itens itensLivro = new Itens();
        itens.nome = "Livro";
        list.Add(itensLivro);

        for (int i = 0; i < list.Count; i++)
        {
            Console.WriteLine("Item: " + list[i].nome);
            //Aqui ele imprime tudo igual a ultima string adicionada
        }
        Console.ReadLine();
    }
}
    
09.10.2017 / 15:53
2

Try adding items this way. I think it will solve your problem.

list.Add(new item{ nome = "GPU" });
list.Add(new item{ nome = "Livro" });
    
09.10.2017 / 16:01