C# 列表对象值被覆盖:引用语义问题
为什么在向列表中添加新值时,列表中的所有项都会覆盖之前的数值?这种令人费解的行为源于 C# 中底层数据结构和引用语义。
理解类和结构体的语义
在 C# 中,类是引用类型,这意味着类类型的变量存储对内存中实际对象位置的引用。另一方面,结构体是值类型,变量直接保存实际数据。
在提供的代码片段中:
<code class="language-csharp">List<Tag> tags = new List<Tag>(); Tag _tag = new Tag(); string[] tagList = new[] { "Foo", "Bar" }; foreach (string t in tagList) { _tag.tagName = t; // 设置所有属性 tags.Add(_tag); // 覆盖之前的数值 }</code>
由于 _tag
是一个引用类型,tags.Add(_tag)
操作将对同一对象的引用添加到列表中。结果,列表中的所有元素实际上都指向同一实例。通过 _tag
修改一个实例会改变列表中的所有项。
通过创建新实例解决问题
为了防止覆盖,应该为循环的每次迭代创建一个新的 Tag
实例:
<code class="language-csharp">foreach (string t in tagList) { Tag _tag = new Tag(); // 为每次迭代创建一个新实例 _tag.tagName = t; tags.Add(_tag); }</code>
现在,每次迭代都会创建一个新的 Tag
实例,确保列表中的每个对象都有其自身独特的值。
额外说明:结构体与类
使用结构体而不是类可以消除覆盖问题,因为结构体是值类型。当结构体被赋值给一个新变量时,它会创建一个全新的实例,包含它自己的一组值。因此,tags.Add(_tag)
执行的是复制操作,不会影响先前添加的项。
总之,理解引用语义以及类和结构体之间的区别对于避免在 C# 中的对象列表中出现覆盖问题至关重要。
以上是为什么我的列表项在 C# 中相互覆盖?的详细内容。更多信息请关注PHP中文网其他相关文章!