为什么 class 被复制而不是被引用?
Why is class copied instead of referenced?
一段时间以来,我一直在努力弄清楚为什么我有时会得到一份数据副本,有时会得到一份参考资料。然后我发现了 reference types
和 value types
。所以我的生活改变了,我开始在编码时使用这些信息。
现在我正在 Unity 中制作自定义编辑器。我有一个 Ability
class,其中包含一个 Buff
列表(增益列表 classes)。所以我拥有的每个能力都可以包含多个增益。
在数据库中编辑能力变量时,我首先获取我正在使用的能力的副本,而不是直接编辑它们而是编辑副本,然后在完成后将副本保存到数据库中。然而,我似乎仍然用一行而不是另一行来复印。所以现在看来我不是在引用引用类型,而是让它表现得像一个值类型。我不明白这是为什么。
//This constructor is used to make a copy of an existing Ability in the database
public Ability(Ability cloneFrom)
{
buffs = new List<Buff>();
//This will work, not cause a reference but actually takes a copy.
//I don't understand that because I am using Add()on a class (reference type)
for (int x = 0; x < cloneFrom.buffs.Count; x++)
buffs.Add(cloneFrom.buffs[x]);
//This will create a reference as expected
buffData = cloneFrom.buffData;
}
我唯一能想到的是 List.Add() 确实进行了复制,但我无法确认。
非常快,确保您了解 class
和 object
之间的区别。 class 是千篇一律; 对象 是 cookie。
我认为 Ron Beyer(从评论中)一针见血——你可能是说你想保持列表同步,这样一个 Ability
的 buffs
对象与另一个Ability
对象保持同步。
这只有在您将一个对象的增益分配给另一个对象时才有效。
如果您调用 Add
,您将获得对增益的引用,但不会添加新的增益。
您提到了值类型与引用类型;快速列表如下(有人跳在这里纠正我)
值类型
- 基本类型(int、float、long、double、bool 等)
- 结构
- 枚举
引用类型
- classes
- 代表
- 接口
- 对象
有一种情况你应该知道:
public class Ability {
public int Score { get; set; }
public Ability(int score) {
Score = score;
}
}
public static void KillReference(Ability ability) {
// When we execute the next line, the ability
// from the original scope will stay the same
ability = new Ability(2);
}
public static void Main() {
Ability ability = new Ability(5);
KillReference(ability);
// ability.Score is still 5
}
OHGODWHY
当您将引用类型传递给函数时,您实际上是在传递一个 "copy" 引用(这与 C/C++ 中的指针相同)...重新有效地按值传递引用(令人困惑,对吧?)。
当您将该引用分配给另一个对象时,被引用的原始对象不再被该变量引用——有一个新变量,对 ability
的所有更改都将针对该新变量(一旦你退出函数的范围,它将从堆中清除。
希望对您有所帮助!
一段时间以来,我一直在努力弄清楚为什么我有时会得到一份数据副本,有时会得到一份参考资料。然后我发现了 reference types
和 value types
。所以我的生活改变了,我开始在编码时使用这些信息。
现在我正在 Unity 中制作自定义编辑器。我有一个 Ability
class,其中包含一个 Buff
列表(增益列表 classes)。所以我拥有的每个能力都可以包含多个增益。
在数据库中编辑能力变量时,我首先获取我正在使用的能力的副本,而不是直接编辑它们而是编辑副本,然后在完成后将副本保存到数据库中。然而,我似乎仍然用一行而不是另一行来复印。所以现在看来我不是在引用引用类型,而是让它表现得像一个值类型。我不明白这是为什么。
//This constructor is used to make a copy of an existing Ability in the database
public Ability(Ability cloneFrom)
{
buffs = new List<Buff>();
//This will work, not cause a reference but actually takes a copy.
//I don't understand that because I am using Add()on a class (reference type)
for (int x = 0; x < cloneFrom.buffs.Count; x++)
buffs.Add(cloneFrom.buffs[x]);
//This will create a reference as expected
buffData = cloneFrom.buffData;
}
我唯一能想到的是 List.Add() 确实进行了复制,但我无法确认。
非常快,确保您了解 class
和 object
之间的区别。 class 是千篇一律; 对象 是 cookie。
我认为 Ron Beyer(从评论中)一针见血——你可能是说你想保持列表同步,这样一个 Ability
的 buffs
对象与另一个Ability
对象保持同步。
这只有在您将一个对象的增益分配给另一个对象时才有效。
如果您调用 Add
,您将获得对增益的引用,但不会添加新的增益。
您提到了值类型与引用类型;快速列表如下(有人跳在这里纠正我)
值类型
- 基本类型(int、float、long、double、bool 等)
- 结构
- 枚举
引用类型
- classes
- 代表
- 接口
- 对象
有一种情况你应该知道:
public class Ability {
public int Score { get; set; }
public Ability(int score) {
Score = score;
}
}
public static void KillReference(Ability ability) {
// When we execute the next line, the ability
// from the original scope will stay the same
ability = new Ability(2);
}
public static void Main() {
Ability ability = new Ability(5);
KillReference(ability);
// ability.Score is still 5
}
OHGODWHY
当您将引用类型传递给函数时,您实际上是在传递一个 "copy" 引用(这与 C/C++ 中的指针相同)...重新有效地按值传递引用(令人困惑,对吧?)。
当您将该引用分配给另一个对象时,被引用的原始对象不再被该变量引用——有一个新变量,对 ability
的所有更改都将针对该新变量(一旦你退出函数的范围,它将从堆中清除。
希望对您有所帮助!