2016-11-19 2 views
5

У меня есть небольшая проблема, когда я хочу выполнить некоторые операции в C#. Я приведу вам небольшой пример.Стек общего списка очищается при удалении пустого списка

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();  
} 

В этом коде я хочу переместить мой связанный список в стек, чем удалить все элементы в списке. Когда я очищаю список, первый индекс моего стека исчезает, потому что он передается по ссылке. Я ошибаюсь? Потому что я не знаю, почему это происходит.

Так что я использую метод pass by value.

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();  
} 

Это хороший способ решить проблему? Таким образом, он работает, но читаемость уменьшается. Что ты предлагаешь мне?

Благодаря ...

+2

«Я не прав?» Да, в коде, который вы показали, нет пропущенных ссылок. Вы можете сказать это из-за отсутствия 'ref' и' out'. Я предлагаю вам прочитать http://jonskeet.uk/csharp/parameters.html и http://jonskeet.uk/csharp/references.html. Обратите внимание, что передача ссылки по значению не совпадает с передачей по ссылке. –

ответ

3

Просто создать новый List<HufmannLetter> объект внутри цикла и добавить, что в стек. Повторное использование одного и того же объекта списка не будет иметь каких-либо преимуществ в производительности.

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); 
} 
+0

Да, я знаю, это не влияет на мою производительность, но я думаю о понятности моего кода. Но если есть какой-либо способ, я не изменю свой код. Большое спасибо :) – Berkin

+1

Ни один из ответов не объясняет OP 'Когда я очищаю список, первый индекс моего стека исчезает, потому что он передается по ссылке. Я ошибаюсь? Потому что я не знаю, почему это происходит. '! –

+0

@ Беркин, что вы подразумеваете под _ «нет никакого пути» _? Мой пример не идентичен вашему. –

1

Вы можете создать new List<HufmannLetter>() и дать в конструкторе предыдущего списка, это создаст новый объект, который будет не очищен.

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

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

EDIT

Так List<T> это ссылочный тип, вы ставите letterList в стеке. Таким образом вы переносите значение ссылки List<T> в стек позиция. Таким образом, переменная letterList ссылается на тот же объект, что и элемент в вашем стеке. Когда вы очищаете элементы из списка букв, они также очищаются в элементе стека.

Проверить, что Reference Types

+1

Ни один из ответов не объясняет OP 'Когда я очищаю список, первый индекс моего стека исчезает, потому что он передается по ссылке. Я ошибаюсь? Потому что я не знаю, почему это происходит. '! –

+0

@Am_I_Helpful Я думаю, что op понимает, почему значения очищаются от его списков в стеке. Если он этого не поймет, я напишу небольшое объяснение. – mybirthname

-1

вы также можете сделать что, как

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

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

или вы можете попробовать это

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

Это тот же ответ, что и botond.botos, который был дан до 6 мин. – mybirthname

+0

Да, но, пожалуйста, проверьте вторую часть –

1

List<> является изменяемый ссылочный тип.

При передаче List<> к способу вы передаете копию с ссылкой. Итак, вы просто скажите, что это List<>. Это не будет копировать (клонировать) все содержимое List<>.

Когда вы (Push) в List<> на Stack<>, что Stack<> действительно держит является копией ссылки на этот экземпляр List<>. Если этот экземпляр позже изменен, например, с .Add("asd") или с .Clear(), эта «мутация» будет видна, следуете ли вы за ссылкой, хранящейся на Stack<> или другой ссылкой, которую вы имеете, от локальной переменной. Обе ссылки «указывают» на тот же экземпляр List<>.

Когда в вашем коде, вы говорите:

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

, который будет изменять (мутировать) существующий экземпляр List<> так он становится пустым. Это изменение будет видно любому, кто имеет ссылку на этот конкретный экземпляр List<>.

Если вместо этого вы сделали:

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

что бы «переехал» ссылка на letterList, чтобы указать на экземпляр List<>новый. Это не повлияет на людей с другими ссылками на «старый» экземпляр.


Названное передачу по ссылке Использование вводит в заблуждение. Это должны были ссылочные типы и передача ссылок или что-то в этом роде.

Смежные вопросы