2017-03-13 6 views
0

msdnでは、「指定したリストからコピーされた要素を含むObservableCollectionクラスの新しいインスタンスを初期化します。ObservableCollection <T>(リスト<T>)

しかし、私はこの動作を理解していない:

私はクラスPersonを持っています。

public class Person 
{ 
    public string Firstname { get; set; } 
    public string Lastname { get; set; } 

    public override string ToString() 
    { 
     return Firstname + " " + Lastname; 
    } 
} 

ここで人のリストを作成します。 次に、リストからコピーされた要素を含むObservableCollectionを作成します。

次に、リスト内の1人とObservableCollection内の1人を変更します。 両方の変更が両方のコレクションに反映されます。どうして?

最後に、1人をリストに追加し、1人をOCに追加します。 追加された項目

public partial class MainWindow : Window 
{ 
    private List<Person> PersonList{ get; set; } 
    private ObservableCollection<Person> PersonObservableCollection { get; set; } 

    public MainWindow() 
    { 
     InitializeComponent(); 

     FillCollections(); 

     listbox1.ItemsSource = PersonList; 
     listbox2.ItemsSource = PersonObservableCollection;    
    } 


    private void FillCollections() 
    { 
     PersonList = LoadDataPerson(); 
     PersonObservableCollection = new ObservableCollection<Person>(PersonList); 

     // Adding a person to the List. 
     PersonList.Add(new Person() { Firstname = "added to List",}); 

     // Adding a person to the ObservableCollection. 
     PersonObservableCollection.Add(new Person() { Firstname = "added to Observable Collection" }); 


     // Changing then name of the first person in the List 
     Person p1 = PersonList[0]; 
     p1.Lastname = "changed in List"; 

     // Changing the name of the second person in the ObservableList 
     Person p2 = PersonObservableCollection[1]; 
     p2.Lastname = "changed in ObservableCollection"; 
    } 


    private List<Person> LoadDataPerson() 
    { 
     List<Person> personen = new List<Person>(); 
     personen.Add(new Person() { Firstname = "John"}); 
     personen.Add(new Person() { Firstname = "Will"}); 
     personen.Add(new Person() { Firstname = "Sam" }); 
     return personen; 
    } 
} 

関連コレクションにXAMLのみreflectetです:

<Window x:Class="ObservableCollection.MainWindow" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
    xmlns:local="clr-namespace:ObservableCollection" 
    mc:Ignorable="d" 
    Title="MainWindow" Height="350" Width="525"> 
<Grid> 
    <Grid.ColumnDefinitions> 
     <ColumnDefinition/> 
     <ColumnDefinition/> 
    </Grid.ColumnDefinitions> 

    <ListBox Grid.Column="0" x:Name="listbox1"/> 
    <ListBox Grid.Column="1" x:Name="listbox2"/> 

</Grid> 

出力は次のようになります。 Output

+1

[参照型](https://msdn.microsoft.com/en-us/library/t63sy5hs.aspx)の仕組みを理解していますか?特に、参照型オブジェクトのリストは、実際にはメモリ内の別の場所にある一意に識別可能なオブジェクトの*参照*のリストであることを理解していますか? – phoog

答えて

1

msdnには、 "指定したリストからコピーされた要素を含むObservableCollectionクラスの新しいインスタンスを初期化します。"

これは当てはまりますが、コピーされるのは要素であり、内容ではなく要素の参照です。

これで、同じ要素を持つ2つのコレクションが作成されました。
リストまたはobservableCollectionから要素を尋ねると、personの同じインスタンスへの参照が取得されます。 それを変更すると、明らかに両方に反映されます。

新しい項目を追加すると、その項目を特定のコレクションに追加すると、その項目はほかの項目にコピーされません。

1

ドキュメントが明確である可能性があります。

は、指定されたリストからコピーした要素が含まれていObservableCollection<T>クラスの新しいインスタンスを初期化:値型の場合は、intのように、それは「コピー」に何を意味するのかは明らかです。

ただし、参照タイプがあります。この参照は2つのリスト間でコピーされているので、両方のリストが同じ基本オブジェクトを指しています。つまり、更新は両方で見られます。

+0

私はこれがドキュメントの誤りであるとは確信していません。 'List '(ここで 'T'は参照型です)が実際には型の* references *のリストであることをプログラマが理解していないのでしょうか? 'T'?これは.NET型システムの基本です。参照の種類に関するすべてのドキュメント(またはおそらく*おそらく*!)参照の型がこの概念をカバーしなければならない場合、ドキュメントは持続不可能な密集になります。 – phoog

+0

@phoogまあまあ、あなたはタイプシステムを理解する必要があります。私はフレーズ_ "要素をコピー" _する方が良い方法があるのだろうかと疑問に思います_でも –

+0

良い点。初心者の読者が必要に応じてそれを追求できるように、*要素*が参考になるかもしれないことを読者に思い出させるために、そこに数語を追加することができます。 – phoog

0

したがって、source code for thisを見ると、その下にあるリストが操作されています。itemsは、プライベートフィールドであることを、ほんの一例である

protected virtual void InsertItem(int index, T item) { 
     items.Insert(index, item); 
    } 

public class Collection<T>: IList<T>, IList, IReadOnlyList<T> 
{ 
    IList<T> items; 
    [NonSerialized] 
    private Object _syncRoot; 

    public Collection() { 
     items = new List<T>(); 
    } 

    public Collection(IList<T> list) { 
     if (list == null) { 
      ThrowHelper.ThrowArgumentNullException(ExceptionArgument.list); 
     } 
     items = list; 
    } 

あなたは両方のコレクション(観測可能な1とあなたのオリジナルの1)を変更したときにはっきりと見ることができるように、変更します両方に反映される。

ObservableCollectionのすべてが上を実行しています。INotifyPropertyChangedを代理しています。

関連する問題