2009-06-18 3 views
1
Dictionary <string, List <SaleItem>> saleItemNew = new Dictionary<string, List< SaleItem>>(); 

saleItems = new List <SaleItem>(); 

saleItemNew.Add("1", saleItems); 

この時点で、辞書のリストには値があります。以前に割り当てられたリストをクリアするとC#辞書の値がクリアされます。なぜですか?

saleItems.Clear(); 

私が以前に割り当てられたリストをクリアするときしかし、辞書の値の一覧は空になり...なぜ?

答えて

11

辞書にはリストと同じ参照が含まれているため、リストを変更すると両方の参照が変更されます。参照型について

Microsoftのドキュメントは:http://msdn.microsoft.com/en-us/library/490f96s2.aspx

+0

私はリストが同じ方法であると仮定していますか? – Dano

+0

はい、そうです。参照を変更する人は、その参照を使用するすべての人のために参照を変更します。参照は基本的なリストへのポインタ以上のものであると考えてください。 – jjxtra

+0

同じ参照を共有しないリストをたくさん追加したい場合は、新しいリスト()を実行し、新しいリストが必要になるたびに辞書に追加してください。 – jjxtra

2

なぜなら、Dictionaryは値の型ではなく、参照であるからです。ディクショナリを別の変数に割り当てると、ディープコピーは実行されません。代わりに、同じオブジェクトの別の参照を指すだけです。 1つのオブジェクトしかないので、いずれかの参照を介してクリアすることは、両方の参照に表示されます。

.Net Frameworkの値の種類とは対照的です。基本的に値型の代入は、データの浅いコピーを実行し、2つの独立したオブジェクトを作成します。値型に参照フィールドがある場合は、2つの値型の2つのフィールドが同じオブジェクトを指していることに注意してください。

1

それはメモリ使用量とポインタに関係しています。スタックにはオブジェクトがあり、ヒープはオブジェクトに割り当てられます。そのメモリはヒープです。 saleItems変数はスタックに定義され、ヒープ上のメモリアドレスを指します。あなたの辞書はヒープを指すスタック上にもあります。あなたが言うとき

saleItems = new List<SaleItem>() 

変数saleItemsはスタックにプッシュし、ヒープ上のデータの場所にメモリアドレスポイントが含まれています。 0x0100と言うことができます。今すぐあなたの辞書に新しいDictionaryItemを追加します。 DictionaryItemは、キーと値の2つのプロパティを持つヒープ上に配置されます。この場合、saleItemsValueと追加したので、Valueの住所は0x0100です。今すぐDictionaryItem.Valueは、saleItemsと同じメモリを指しています。 saleItems.Clearを呼び出すと、アドレス0x0100にリストがあり、すべてのアイテムが削除されます。したがって、辞書と変数は同じメモリを指しているため、両方とも空になります。あなたがしたいことは、もう一度saleItems = new List<SaleItem>();と言うことです。今、saleItemsはヒープ上の新しいアドレスを指します(例えば、0x0200)。 DictionaryItem.Valueはまだメモリアドレス0x0100を指しているので、辞書のデータに影響を与えることなくsaleItems変数に作用することができます。 C#でのスタックとヒープの詳細については

この記事を試してみてください。http://www.c-sharpcorner.com/UploadFile/rmcochran/csharp_memory01122006130034PM/csharp_memory.aspx?ArticleID=9adb0e3c-b3f6-40b5-98b5-413b6d348b91

+1

これは実装の詳細です。注目すべき点は、内部でどのように実装されるかの詳細ではなく、「参照型」と「値型」です。 – jason

+1

IMO - 'value type'と 'reference type'というモニカは、基礎となるメモリの使用方法を理解していない限り、スタックとヒープとその関係を理解する必要があります。クラス、デリゲートなどは参照型ですが、参照型とはどういう意味ですか?これは、スタック上のメモリがヒープ内のメモリアドレスを参照するために使用されることを意味します。インッツ、ブール、列挙型は値型ですが、それはどういう意味ですか?これは、真の値を格納するためにスタック上でメモリが使用されることを意味します。 IMOこれは理解するために不可欠です。 – NerdFury

0

は、辞書にリストを追加するだけで浅いコピーです...同じ値を持つ新しいリストが作成され、追加されません(A深いコピー)。むしろ古いリストへの参照が追加されます。

0

同じ参照を使用します。それを行うには

良い方法は

Dictionary <string, List <SaleItem>> saleItemNew = new Dictionary<string, List<SaleItem>>(); 
saleItemNew.Add("1", new List<SaleItem>()); 

そして、それは参照型であるように、メモリ内の値へのポインタのみが値そのものではないコピーされ

saleItemNew["1"] = new List<SaleItem>(); 
0

をクリアするためです。 あなたは、コンストラクタであなたが望む行動をspecifiyすることができます

ドットネットのPerlから:// // 2番目のオブジェクトに辞書をコピーします。 // 辞書コピー=新しい辞書(辞書);

関連する問題