6

I have a little problem when i want to do some operations in c#. I will give you a little example.

Stack<List<HufmannLetter>> steps = new Stack<List<HufmannLetter>>();
List<HufmannLetter> letterList = new List<HufmannLetter>();    

while(true){

    letterList.Add("asd");
    letterList.Add("sad");

    steps.Push(letterList);
    letterlist.Clear();    
}

In this code, I want to push my linkedlist to a stack than remove all the items in the list. When I clear the list, my stack's first index disappears because it passed by reference. Am i wrong? Because I dont know why it happens.

So I use pass by value method.

Stack<List<HufmannLetter>> steps = new Stack<List<HufmannLetter>>();
List<HufmannLetter> letterList = new List<HufmannLetter>();

while(true) {

    letterList.Add("asd");
    letterList.Add("sad");

    List<HufmannLetter> tempLetterList = new List<HufmannLetter>(letterList);
    steps.Push(tempLetterList);
    letterlist.Clear();    
}

Is it a good way to solve a problem? This way it is working, but readability decreases. What do you suggest me?

Thanks...

Gabriel Rainha
  • 1,713
  • 1
  • 21
  • 34
Berkin
  • 1,565
  • 5
  • 22
  • 48
  • 2
    "Am i wrong?" Yes, there's no pass-by-reference in the code you've shown. You can tell that by the lack of `ref` and `out`. I suggest you read http://jonskeet.uk/csharp/parameters.html and http://jonskeet.uk/csharp/references.html Note that passing a reference by value is not the same as pass-by-reference. – Jon Skeet Nov 19 '16 at 18:33

4 Answers4

3

Just create a new List<HufmannLetter> object inside the loop and add that to the stack. Reusing the same list object won't have any performance benefits.

Stack<List<HufmannLetter>> steps = new Stack<List<HufmannLetter>>();

while(true)
{
    List<HufmannLetter> letterList = new List<HufmannLetter>();

    letterList.Add("asd");
    letterList.Add("sad");

    steps.push(letterList);
}
Botond Botos
  • 1,202
  • 13
  • 20
  • Yeah i know, it doesnt effect my performance but im considering about my code's understandability. But if there arent any way, i wont change my code. Thanks a lot :) – Berkin Nov 19 '16 at 18:15
  • 1
    None of the answers explain OP's `When i clear the list, my stack's first index disappears because it passed by reference. Am i wrong? Because i dont know why it happens.`! – Am_I_Helpful Nov 19 '16 at 18:21
  • @Berkin, what do you mean by _"there aren't any way"_? My example is not identical to yours. – Botond Botos Nov 19 '16 at 18:28
1

You can create new List<HufmannLetter>() and give in the constructor the previous list, this will create new object which will be not cleared.

while(condition)
{
    letterList.Add("asd");
    letterList.Add("sad");

    steps.push(new List<HufmannLetter>(letterList));
    letterlist.Clear();
}

EDIT

So List<T> is reference type, you are putting the letterList in the stack. In this way you are transferring the value of the reference List<T> in the stack item. So your letterList variable reference the same object as the item in your stack. When you clear the items from letterList, they are cleared in the item of the stack too.

Check what is Reference Types

mybirthname
  • 17,949
  • 3
  • 31
  • 55
  • 1
    None of the answers explain OP's `When i clear the list, my stack's first index disappears because it passed by reference. Am i wrong? Because i dont know why it happens.`! – Am_I_Helpful Nov 19 '16 at 18:21
  • @Am_I_Helpful I think the op understands why the values are cleared from his lists in the stack. If he doesn't understand it I will write a little explanation. – mybirthname Nov 19 '16 at 18:23
1

List<> is a mutable reference type.

When you pass a List<> to a method, you pass a copy of the reference. So you just tell which List<> it is. That will not copy (clone) the entire contents of the List<>.

When you put (Push) a List<> on the Stack<>, what the Stack<> really keeps is a copy of a reference to this instance of List<>. If that instance is later modified, for example with .Add("asd") or with .Clear(), this "mutation" will be seen whether you follow the reference kept by the Stack<> or another reference you have, from the local variable. Both references "point" to the same instance of List<>.

When, in your code, you say:

letterList.Clear(); // do not change reference, follow reference and mutate the instance it refers to

that will modify (mutate) the existing instance of List<> so it becomes empty. This change will be seen by anyone holding a reference to this particular instance of List<>.

If instead you had done:

letterList = new List<string>(); // create new instance, change reference to point there (reference assignment), old instance is unchanged

that would have "moved" the reference of letterList to point to a new instance of List<>. This would not affect people with other references to the "old" instance.


The title Pass By Reference Usage is misleading. It should have been Reference Types And Passing References or something like that.

Jeppe Stig Nielsen
  • 60,409
  • 11
  • 110
  • 181
-1

you can also do that as

Stack<List<HufmannLetter>> steps = new Stack<List<HufmannLetter>>();

while(true)
{
var tempList = new List<HufmannLetter>;
tempList.add("asd");
steps.push(tempList);
 }

or you can try this

steps.push(tempList.ToList());
   tempList.Clear();