简体   繁体   English

更改对象数组中的一个元素会更改所有元素,C#,如何按值分配对象

[英]Changing one element in array of objects changes all elements, c#, how do I assign objects by value

I'm new to c#, and I think I'm confused about how to assign objects by value rather than reference. 我是C#的新手,我对如何通过值而不是引用分配对象感到困惑。 In the following code, I have a constructor taking a default object for the posGrid to be filled with. 在下面的代码中,我有一个构造函数,使用默认对象填充posGrid。 I want these all to be merely copies of the default object, but when I change one, they all change. 我希望这些都只是默认对象的副本,但是当我更改一个默认对象时,它们都会更改。 I assume this is because I'm initializing the array with references to the object, but how do I assign them just the value? 我认为这是因为我正在使用对对象的引用来初始化数组,但是如何只给它们分配值呢?

public Grid (int width, int height, Unit defaultUnit)
{
    Random rand = new Random();
    this.width = width;
    this.height = height;

    posGrid = new Unit [height, width];
    for (int y = 0; y < height; y++)
        for (int u = 0; u < width; u++)
            posGrid[y, u] = defaultUnit;
}

Variable types 变量类型

Variables like int, long are value types and have it's own memory space and contains the value. 像int,long这样的变量是值类型,并且具有自己的内存空间并包含值。

Reference types 参考类型

Variable values of string, class .. are not directly stored. 字符串class ..的变量值不直接存储。 The value is stored in a other memory space and a pointer stores this adress and is pointing to it. 该值存储在另一个存储空间中,并且指针存储该地址并指向它。

Solution

So for your problem you have so create a new Unit based on the values of defaultUnit. 因此,对于您的问题,您必须基于defaultUnit的值创建一个新的Unit。

There are many ways you could solve this problem. 有很多方法可以解决此问题。

The simplest way is to make Unit a struct: 最简单的方法是将Unit构造为:

struct Unit { ... }

Since structs are value types, a copy of Unit is automatically created when you assign it to something, as opposed to the reference being copied. 由于structs是值类型,因此将Unit分配给某物时会自动创建Unit的副本,而不是复制引用。 However, there might be some features of classes that you want Unit to have (eg having a base class), in which case you need another method. 但是,您可能希望Unit具有某些类的功能(例如,具有基类),在这种情况下,您需要另一个方法。


Alternatively, you can add a CreateCopy method: 或者,您可以添加CreateCopy方法:

public Unit CreateCopy() {
    Unit copy = new Unit();
    copy.Property1 = this.Property1;
    copy.Property2 = this.Property2;
    // etc
    return copy;
}

And call it when you create the array: 并在创建数组时调用它:

posGrid = new Unit [height, width];
for (int y = 0; y < height; y++)
    for (int u = 0; u < width; u++)
        posGrid[y, u] = defaultUnit.CreateCopy(); // <----

You can also achieve this by implementing ICloneable . 您还可以通过实现ICloneable实现此目的。


A third method is to have the constructor of Grid accept all the data needed to create the unit as parameters, instead of the Unit object itself. 第三种方法是让Grid的构造函数接受创建单元所需的所有数据作为参数,而不是Unit对象本身。 And then the constructor can create the Unit objects on its own. 然后,构造函数可以自己创建Unit对象。

public Grid (int width, int height, SomeType defaultUnitProperty1, SomeType defaultUnitProperty2)
{
    Random rand = new Random();
    this.width = width;
    this.height = height;

    posGrid = new Unit [height, width];
    for (int y = 0; y < height; y++)
        for (int u = 0; u < width; u++)
            posGrid[y, u] = new Unit(defaultUnitProperty1, defaultUnitProperty2);
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM