2016-04-25 16 views
0

リストからアイテムを見つけてそのプロパティの1つを変更しようとすると、変更されません。構造体がリスト内にあるときに構造体フィールドを変更

// My struct 
struct Person 
{ 
    public string name; 
    public string surname; 
} 

// Fill up initial data 
persons = new List<Person>(); 
person = new Person(); 
person.name = "Name"; 
person.surname = "Test"; 
persons.Add(person); 

// Here person is found, I can see it by printing person.name and person.surname 
Person foundPerson = persons.Find(p => p.surname == "Test"); 

// Let's change it 
foundPerson.name = "Another name"; 

// But when I print all list's items, the name is still "Name". So previous string hasn't changed the original object. 
persons.ForEach(delegate (Person person) 
{ 
    Console.WriteLine("Name: {0}", person.name); 
}); 

私は何が欠けていますか?私のリストに含まれている元の値を変更するにはどうすればよいですか?

答えて

4

構造体を使用しているためです。構造体は値で処理されるので、書き込むときには

Person person list.Find(p => p.surname == "Test"); 

が得られます。

構造体の代わりにクラスを使用するか、full person構造体をリストするために書き戻します。

それでも構造体を使用したい場合は、struct sがバイ値オブジェクトであるためです

Person foundPerson = persons.Find(p => p.surname == "Test"); 
int index = persons.IndexOf(foundPerson); 
foundPerson.name = "Another name"; 
persons[index] = foundPerson; 
+0

ありがとうございます。しかし、構造体が値によって処理される場合、奇妙なことがあります。構造体の中にListフィールドがあり、そのリストに何かを追加すると(例えば 'foundPerson.list.Add(someAnotherStruct)')、それは 'persons'リストから元の構造体に保存されます。どうして?あなたが言っていることが真実ならば、元のリストは影響を受けてはいけません。 – Hast

+0

Listはクラスなので、構造体内のリストへのポインタを格納します。構造体のコピーを取得すると、その中にポインタのコピーがありますが、このポインタは引き続き同じリストを指しています。 – Artem

2

を書くことができます。これを行うと

Person foundPerson = persons.Find(p => p.surname == "Test"); 

foundPersonはあなたのリストからPersonstructの独立したコピーになります。変更はオリジナルに反映されません。

これは、Personclassとすることで解決できます。この変更を行う柔軟性がない場合は、インデックスを検索してその場所で変更を行うか、Personを不変であるかのように扱い、変更されたfoundPersonをリストに格納された位置に戻します。

あなたの質問は、なぜit is a good idea to stay away from mutable structsなのかを完全に説明しています。

関連する問題