0

私はC#が初めてなので、ご容赦ください。クラスと構造体のどちらが必要かを判断できない c# の問題があります。クラスまたは構造体のリストを作成し、それに要素を追加しています。構造体を使用すると、アイテムを追加して変更し、再度追加することができます。値によって渡されるため、変更が表示されます。問題は、構造体が可変ではないため、後で要素を編集できないことです。クラスを使用する場合、項目を追加して変更すると、リスト内のすべての項目が変更されます。異なるものにしたい場合は、毎回オブジェクトの新しいインスタンスを作成する必要があります。しかし、1 つのアイテムだけを変更したいオブジェクトがあるので、他のすべてのアイテムを新しいオブジェクトにコピーする必要があります。なぜ?より良い解決策はありますか?

このコードは私の問題を示しています:

namespace TestError
{
    public partial class Form1 : Form
    {
        private List<Thing> lst;
        private Thing obj;

        public Form1()
        {
            InitializeComponent();

            lst = new List<Thing>();
            obj = new Thing();

            obj.a = "bla";
            lst.Add(obj);
            //obj = new Thing();
            obj.a = "thing";
            lst.Add(obj);

            foreach (Thing t in lst)
                listBox1.Items.Add(t.a);
        }
    }

    class Thing
    {
        public string a;
        //problem is there are many more items here that don't change!
    }
}

構造体が機能しない理由:

namespace TestError
{
    public partial class Form1 : Form
    {
        private List<Thing> lst;
        private Thing obj;

        public Form1()
        {
            InitializeComponent();

            lst = new List<Thing>();
            obj = new Thing();

            obj.a = "bla";
            lst.Add(obj);
            lst[0].a = "new";  //error. if i change it to class, it works.
            obj.a = "thing";
            lst.Add(obj);

            foreach (Thing t in lst)
                listBox1.Items.Add(t.a);
        }
    }

    struct Thing
    {
        public string a;
    }
}
4

2 に答える 2

0

クラスは行く方法です。私は大学を卒業して以来、構造体型に触れたことはありません。

モノのクラスについては、「ここには変わらないアイテムがもっとたくさんあります!」とおっしゃいました。つまり、値が固定されているか、値が初期オブジェクトに基づいているということです。値が固定されている場合は、クラスにいくつかのデフォルト値を割り当てることができます。

値が最初のオブジェクトに基づいている場合、オブジェクトをリストに追加する際に変数を渡す手間はありません。

于 2013-06-28T06:28:17.120 に答える
0

問題は、構造体が可変ではないため、後で要素を編集できないことです。

これはまったく正しくありません。誤解しないでください、あなたがここでやろうとしていることをするのは本当に悪い考えclassだと思います.Clone()メソッドを使用するのが最善の解決策だと思いますが、これを考えている理由はまさに価値によるものです-型セマンティクス。リスト インデクサー ( [0]) はメソッドであり、直接アクセスではないことに注意してください。検討:

lst[0].a = "new";

この行がコンパイルされた場合、次のようになります。

  • リストからオブジェクトのコピーを取得します(これは完全に分離された別のコピーです)
  • コピーのフィールドを変更する
  • コピーを捨てる

コンパイラは、これが間違いなく意図したものではないことを認識しているため、間違いを防ぐことができます。使用法は次のとおりです。

var tmp = lst[0];
tmp.a = "new";
lst[0].a = tmp;

奇妙なことに、もしlstarrayあれば、それはうまくいくでしょう- 配列はその場での直接編集を可能にします:

lst[0].a = "new";

コンパイルします。ただし、これは行わないでください:

  • 変更可能な構造体は悪い考えであり、コードに多くの混乱を引き起こします
  • public フィールド悪い考えです
  • 大きな構造体悪い考えです

私が言うように、ここでの私のアドバイスはclass; 便利なコピーセマンティクスが必要な場合は、メソッドを追加しますClone()

于 2013-06-28T06:49:54.437 に答える