2016-11-19 22 views
5

私はC#でいくつかの操作をしたいときに少し問題があります。私はあなたに少しの例を与えます。プッシュされたリストがクリアされると、ジェネリックリストのスタックがクリアされます

このコードでは、リンクされたリストをスタックにプッシュして、リスト内のすべてのアイテムを削除します。リストをクリアすると、スタックの最初のインデックスが参照渡しされて消えます。私が間違っている?私はなぜそれが起こるのか知りません。

私は値渡しメソッドを使用します。

問題を解決するには良い方法ですか?このようにして動作しますが、可読性は低下します。あなたは私に何をお勧めしますか?

おかげで...

+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変数は、スタック内の項目と同じオブジェクトを参照します。 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

これは6分前に与えられたbotond.botosと同じ答えです。 – mybirthname

+0

はい、それは2番目の部分を確認してください –

1

List<>を試すことができますが、変更可能な参照型であることを行うことができます。

List<>をメソッドに渡すときは、のコピーを渡します。だからあなたはただそれがList<>だと言うだけです。それはList<>の内容全体をコピー(複製)しません。

あなたはStack<>上(PushList<>を入れた場合、どのようなStack<>が本当に保持するList<>のこのインスタンスへの参照のコピーです。このインスタンスが後で.Add("asd").Clear()などのように後で変更された場合は、Stack<>または他のリファレンスが保持する参照をローカル変数に従うかどうかにかかわらず、この「突然変異」が表示されます。 両方の参照は、同じインスタンスList<>に "ポイント"します。

すると、あなたのコードでは、あなたが言う:

List<>の既存のインスタンスは、それが空になる(変異する)変更します
letterList.Clear(); // do not change reference, follow reference and mutate the instance it refers to 

。この変更は、List<>のこの特定のインスタンスへの参照を保持している人に見られます。

あなたが行っていた代わりにした場合:

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

List<>新しいインスタンスを指すようにletterListの参照を「移動」しているということ。これは、「古い」インスタンスへの他の参照を持つ人々には影響しません。


リファレンス使用ことでタイトルパスが誤解を招くおそれがあります。参照型や参照渡しなど、そのようなものだったはずです。

関連する問題