0

我是 C# 新手,所以请耐心等待。我在 c# 中有一个问题,我无法决定我需要一个类还是一个结构。我正在创建一个类或结构的列表并向其添加元素。如果我使用结构,那么我可以添加一个项目,更改它,然后再次添加它,并且将看到更改,因为它是按值传递的。问题是,结构不是可变的,所以我以后不能编辑任何元素。如果我使用一个类,那么如果我添加一个项目并更改它,列表中的所有项目都会更改。如果我希望它有所不同,我必须每次都创建一个新的对象实例。但是我有一个对象,我只想更改一个项目,所以我必须将所有其他项目复制到新对象?!为什么?有更好的解决方案吗?

这段代码说明了我的问题:

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

上课是要走的路。自从我离开大学以来,我从未接触过 struct 类型。

对于 Thing 类,您说“这里还有很多不变的项目!”。这意味着值是固定的还是值基于初始对象。如果值是固定的,您可以在类中分配一些默认值。

如果这些值基于初始对象,我看不到在将对象添加到列表时传递变量的麻烦。

于 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;

奇怪的是,虽然 - 如果lst是一个数组,那么它起作用 - 数组允许直接原位编辑:

lst[0].a = "new";

会编译。但是,请不要这样做

  • 可变结构是一个坏主意,在您的代码中引起很多混乱
  • 公共领域也是一个坏主意
  • 大型结构也是一个坏主意

就像我说的,我的建议是class; 如果您想要方便的复制语义,请添加一个Clone()方法

于 2013-06-28T06:49:54.437 回答