0
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?

Alexei Levenkov
  • 98,904
  • 14
  • 127
  • 179
Nys
  • 99
  • 1
  • 9
  • 5
    correct, you passed a REFERENCE to list. – Leszek P Dec 11 '18 at 13:36
  • 1
    Because reference and value (read this: https://stackoverflow.com/questions/23107941/c-sharp-value-and-reference-types) – aloisdg Dec 11 '18 at 13:36
  • `c` does not contain a new List, it contains a reference to the original list `a`, so calling `Clear` on `a` also clears the List in `cl` because they are the same thing – Liam Dec 11 '18 at 13:36
  • When you update a list via **any** variable that **referencess** it, this change is reflected in **all** references. – MakePeaceGreatAgain Dec 11 '18 at 13:37
  • I'd suggest you read up on [reference types](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/reference-types) – Liam Dec 11 '18 at 13:37
  • There is only one list overall, no matter how many variables point to it. Hint: How many times do you call `new List()`? Once. – David Dec 11 '18 at 13:38
  • You could change your class as `public cl(IEnumerable l)`. Then pass a `List.ToArray()` and `this.l = l.To.List();` – Jimi Dec 11 '18 at 13:47

3 Answers3

0

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.

Alessio Raddi
  • 540
  • 1
  • 6
  • 20
0

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.

Miamy
  • 2,162
  • 3
  • 15
  • 32
0
 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);
Başar Kaya
  • 354
  • 6
  • 13