0

基本的な質問かもしれませんが、これがどのように機能するかを誰かが説明できますか? 以下のコードは単なる例ですが、リアルタイムではさまざまな場所でこのシナリオが発生する可能性があります。例: Orders プロパティを持つ Customer のような複雑なオブジェクトの DTO を作成するとき。Orders (=List) は Customer のコンストラクターでインスタンス化する必要がありますか、それともクエリの結果またはストアド プロシージャに直接割り当てる必要がありますか。

List<string> list1 = new List<string>()
{
    "One", "Two","Three"
};

List<string> list2 = new List<string>();
list2 = list1;        
foreach (var s in list2)
  Console.WriteLine(s);

List<string> list3 = list1;
if (list3 != null) //is this the only difference
{
 foreach (var s in list3)     
     Console.WriteLine(s);     
}

ILコードをチェックしてみましたが、自明ではありませんでした。

    IL_0031: stloc.0
    IL_0032: newobj instance void class [mscorlib]System.Collections.Generic.List`1<string>::.ctor()
    IL_0037: stloc.1
    IL_0038: ldloc.0
    IL_0039: stloc.1
    IL_003a: ldloc.0
    IL_003b: stloc.2
    IL_003c: nop
    IL_003d: ldloc.1
    IL_003e: callvirt instance valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator<!0> class [mscorlib]System.Collections.Generic.List`1<string>::GetEnumerator()
    IL_0043: stloc.s CS$5$0000

紛らわしい例を投稿して申し訳ありません。以下は実際のシナリオです

DTO:

public class CustomerBO
{
        public CustomerBO()
        {
            Orders = new List<OrderBO>(); 
        }
       List<OrderBO>() Orders { get; set;}
      //other properties of customer
}

今DAL層で:

objCustomer.Orders = Repository.GetAll<OrderBO>("dbo.GetOrdersList");

私の質問は、CustomerBO コンストラクターで Orders オブジェクトを初期化 (または) スキップして、プレゼンテーション層で null をチェックしても問題ないでしょうか。

4

5 に答える 5

2

行:はリストをコピーしていません。C#のすべてのクラスと同様に、は参照型である ため、リストへの参照List<string> list3 = list1;をコピーしているだけです。これは新しいリストではなく、上記と同じリストにアクセスするための別の方法です。それは問題ないかもしれませんが、そうではないかもしれませんが、あまり工夫されていない例では、どれを期待しているのか、どれが必要なのかを判断するのは難しいです。Listlist3

if (list3 != null) //is this the only difference

その行が必要かどうかについては、状況によって異なります。リストの作成とそれを使用する間に実行されているコードがあり、list3nullになる可能性がある場合は、それをチェックすることをお勧めします。より「実際の」例がなければ、見分けるのは困難です。list3与えられた例では、nullになることはできなかったので、それは必要ありません。

new List<string>()また、行に含める理由がないことにも注意してくださいList<string> list2 = new List<string>();list1すぐに割り当てるだけlist2なので、新しく作成したリストを使用する前に破棄します。

于 2012-11-29T21:34:13.960 に答える
2

list2: 最初に空のリストを作成し、次にそれを削除して、list2 が list1 と同じオブジェクトを指すようにします。

list3: list1 と同じオブジェクトを直接指します。

于 2012-11-29T21:32:22.637 に答える
1
List<string> list1 = new List<string>()
{
    "One", "Two","Three"
};

例え:メモ帳から1枚の紙をはがし、上部に「この紙は「list1」と呼ばれます」と書きます。新しい家を建て、「1」、「2」、「3」を家に入れ、家の住所を紙に書きます。

List<string> list2 = new List<string>();

例え:メモ帳から1枚の紙をはがし、上部に「この紙は「list2」と呼ばれます」と書きます。新しい家を建てて、その家の住所を紙に書きます。

list2 = list1;      

類推:「list2」という紙からアドレスを消去し、「list1」という紙からアドレスをコピーします。現在、両方の論文が同じアドレスを保持しています。

含意:建築部門は時々みんなの書類をチェックします。彼らは各紙の各住所に行き、そこで見つけた家に緑色のチェックマークを塗ります。次に、緑色のチェックマークのないすべての家を取り壊します。作成したばかりの家(「list2」の紙に住所を上書きした家)は、近い将来破壊されます。誰もその家に足を踏み入れることはなく、それを建てるあなたの努力は無駄になりました。

foreach (var s in list2)
  Console.WriteLine(s);

アナロジー:「list2」紙の住所に行き、家の中から各アイテムを入手して、新聞に印刷します(申し訳ありませんが、アナロジーは壊れています!)

List<string> list3 = list1;

例え:メモ帳から1枚の紙をはがし、上部に「この紙は「list3」と呼ばれます」と書きます。アドレスを「list1」からこの新しい「list3」の紙にコピーします。

if (list3 != null) //is this the only difference
{

類推:「list3」紙に住所が書かれているかどうかを確認します。(ちなみに、このコードにはアドレスが書き込まれている必要があることを証明できるため、これは必要ありません。)

 foreach (var s in list3)     
     Console.WriteLine(s);     
}

例え:「list3」紙の住所に行き、家の中から各アイテムを入手して、新聞に印刷します。当然のことながら、この時点ではすべての論文の住所が同じであるため、同じ家に行くことになります。したがって、同じ家の内容を2回リストします。

于 2012-11-29T21:51:45.010 に答える
1

以下の例で、リスト オブジェクトの割り当てと新しいリスト オブジェクトの作成の違いが明確になると思います。

var l1 = new List<string>()
{
    "One", "Two","Three"
};

var l2 = l1;
l1.SequenceEqual(l2);           // true
Object.ReferenceEquals(l1, l2); // true

var l3 = new List<string>();
foreach (var s in l1)
    l3.Add(s);
l1.SequenceEqual(l3);           // true
Object.ReferenceEquals(l1, l3); // false
于 2012-11-29T21:43:46.703 に答える
1

再割り当てする必要はありません。変数を宣言すると、メモリはデータのアドレスを格納するために予約されます。のような割り当てを行っているときは、 と同じメモリ アドレスを参照するように参照をlist2 = list1設定しています。list2list1

最初に初期化list2すると、使用されずにガベージ コレクターによって再利用されるオブジェクトが作成されます。

于 2012-11-29T21:33:46.383 に答える