8

これを想像してみてくださいstruct

        struct Person
        {
             public string FirstName { get; set; }
             public string LastName { get; set; }
        }

そして次のコード:

        var list = new List<Person>();
        list.Add(new Person { FirstName = "F1", LastName = "L1" });
        list.Add(new Person { FirstName = "F2", LastName = "L2" });
        list.Add(new Person { FirstName = "F3", LastName = "L3" });

        // Can't modify the expression because it's not a variable
        list[1].FirstName = "F22";

の値を変更したい場合Property、次のエラーが発生します。

Can't modify the expression because it's not a variable

一方、配列内で変更しようとすると、Person[]エラーなしで動作しましたが、ジェネリックコレクションで使用する場合、コードに問題はありますか?

4

3 に答える 3

14

インデクサーstructを介してviaを返すと、エントリのコピーが返されます。したがって、そこに割り当てた場合、それはただ捨てられます。したがって、コンパイラエラー。List[]FirstName

Personを参照型に書き直すかclass、完全に再割り当てします。

Person person = list[1];
person.FirstName = "F22";
list[1] = person;

一般的に言えば、可変構造体は、将来的に頭痛の種となる可能性のあるこのような問題を引き起こします。それらを使用する本当に正当な理由がない限り、Personタイプを変更することを強く検討する必要があります。

可変構造体が「悪」なのはなぜですか?

于 2013-02-18T20:59:43.820 に答える
5

明らかに、質問の一部はまだ答えられていません。List<Person>との違いは何ですかPerson[]。インデックスによる要素の取得Listに関しては、値型インスタンスのコピーを返すインデクサー(メソッド)を呼び出します。インデックスによる反対の配列では、コピーではなく、インデックスの要素へのマネージポインターを返します(特別なIL命令ldelemaを使用)。

もちろん、他の回答で述べられているように、可変値型は悪です。簡単な例を見てください。

var en = new {Ints = new List<int>{1,2,3}.GetEnumerator()};
while(en.Ints.MoveNext())
{
    Console.WriteLine(x.Ints.Current);
}

驚いた?

于 2013-02-19T13:04:33.350 に答える
0

そのようにやり直してくださいstruct

    struct Person
    {
         private readonly string firstName;
         private readonly string lastName;
         public Person(string firstName, string lastName)
         {
             this.firstName = firstName;
             this.lastName = lastName;
         }
         public string FirstName { get { return this.firstName; } }
         public string LastName { get { return this.lastName; } }
    }

そして次のコード:

    var list = new List<Person>();
    list.Add(new Person("F1", "L1"));
    list.Add(new Person("F2", "L2"));
    list.Add(new Person("F3", "L3"));

    // Can modify the expression because it's a new instance
    list[1] = new Person("F22", list[1].LastName);

これは、のコピーセマンティクスによるものですstruct。それを不変にし、それらの制約内で機能すれば、問題はなくなります。

于 2013-02-18T21:26:15.393 に答える