2011-01-10 15 views
0

IEnumerableでToArray()が呼び出されたときに何が起こるか理解できません。私はいつも参照のみがコピーされていると仮定してきました。IEnumerableでToArray()が呼び出されるとどうなりますか?

私はここでの出力があることを期待する:ここで何が起こっているか 真 真

しかし、その代わりに、私は 真 偽

を取得しますか?

class One { 
    public bool Foo { get; set; } 
} 

class Two 
{ 
    public bool Foo { get; set; } 
} 

void Main() 
{ 
    var collection1 = new[] { new One(), new One() }; 

    IEnumerable<Two> stuff = Convert(collection1); 

    var firstOne = stuff.First(); 

    firstOne.Foo = true; 

    Console.WriteLine (firstOne.Foo); 

    var array = stuff.ToArray(); 

    Console.WriteLine (array[0].Foo); 
} 

IEnumerable<Two> Convert(IEnumerable<One> col1) { 

    return 
     from c in col1 
     select new Two() { 
      Foo = c.Foo 
     }; 
} 

答えて

4

問題は次のとおりです。ライン

var firstOne = stuff.First(); 

が実行されると、コレクションcollection1が繰り返されるとTwoの新しいインスタンスが返されます。ライン

var array = stuff.ToArray(); 

が実行されると、収集collectionはアゲイン繰り返されるとTwoの新しいインスタンスは、コレクションの最初の要素のための新たなインスタンスを含む、返されます。特に、これはfirstOneとは異なるインスタンスです。したがって、Object.ReferenceEquals(firstOne, array[0])falseであることになります(書かれているように、Object.ReferenceEquals(stuff.First()、stuff.First())はfalseとなります)。これはあなたが見ている問題の原因です。この問題を回避するには

いずれかの方法は、collection1が正確に一度、その後Object.ReferenceEquals(firstOne, array[0])繰り返されるtrueになるように、あなたは

IEnumerable<Two> stuff = Convert(collection1).ToList(); 

または

IEnumerable<Two> Convert(IEnumerable<One> col1) { 
    return col1.Select(x => new Two { Foo = x.Foo}).ToList(); 
} 

を言う必要があります。

+0

明らかにするには、問題は、反復と各列挙時の新しいオブジェクトの作成の組み合わせによる問題です。列挙によって元のオブジェクトが返された場合(新しいインスタンスを作成せずに)、反復処理で元の更新オブジェクトが引き続き取得されます。 –

4

.ToArray()はこちらです。 Convert関数では、Twoの完全に無関係のインスタンスを作成し、Oneインスタンスから取得するブール値ではなく、参照型)にプロパティを設定しています。 Twoの新しく作成されたインスタンスに変更を加えた場合、ではなくOneインスタンスに影響します。彼らはどのような関係もありません。

あなたConvertがこのやった場合:

IEnumerable<One> Convert(IEnumerable<One> input) { 
    return from i in input 
      select i; 
} 

を、あなたが期待する結果を得ると思います。

+0

実際に変換されたリストで作業しています。この場合、クラスOneは影響を受けません。 – Rob

+0

@Rob: 'One'は参照型です。私のバージョンの 'Convert'には' new One {..} 'はありません。同じインスタンスへの参照を返します。 –

+1

私は理解していますが、問題はconvert関数ではありません。彼は元のコレクションではなく、返されたコレクションにFooプロパティを設定しています。彼がOneクラスを削除して、変換せずに同じコードを実行した場合(2つのコレクションを作成するだけで同じ問題が発生します)。 – Rob

関連する問題