您现在的位置是:首页 >学无止境 >Unity中使用struct和class来存储数据的注意事项网站首页学无止境
Unity中使用struct和class来存储数据的注意事项
在 Unity 中,struct 和 class 都是用来定义自定义类型的关键字。它们的主要区别在于如何存储和传递它们的实例。
特点 | struct | class |
---|---|---|
存储方式 | 值类型 | 引用类型 |
默认构造函数 | 自动 | 有 |
性能 | 快 | 慢 |
可空性 | 不可空 | 可空 |
继承 | 单继承 | 单继承或多重继承 |
一、相似之处
1、都是用来定义自定义类型的关键字。
2、都可以包含字段、属性、方法和构造函数等成员。
3、都支持继承、多态和接口实现等面向对象编程的特性。
4、都可以用作方法的参数和返回值类型。
二、不同之处
- 存储方式
class 是引用类型,它的实例存储在堆上,并且变量存储的是指向实例的引用;而 struct 是值类型,它的实例存储在栈上或在堆上的 value 类型对象中,变量存储的是实例本身的值。 - 默认构造函数
class 有一个默认的无参构造函数,而 struct 没有。如果你定义一个 struct,并且没有提供任何构造函数,编译器将自动生成一个默认的无参构造函数。 - 性能
由于 class 是引用类型,它们通常比 struct 更消耗内存,因为每个实例都需要存储一个引用。此外,在传递 class 实例时,实际上只传递了一个引用,而不是整个对象。这意味着,如果对传递的 class 实例进行更改,原始对象也会受到影响。相比之下,struct 是值类型,它们在传递时会进行复制,这可能会导致性能问题,特别是在处理大量数据时。 - 可空性
class 可以设置为 null,而 struct 不可以。如果你需要在某些情况下使用 null 值,应该使用 class。 - 继承
class 支持单继承和多重继承,而 struct 只支持单继承。
在 Unity 中,由于游戏对象和组件都是引用类型,通常建议使用 class 来定义自定义组件和脚本,以便更好地利用 Unity 的引用类型机制。但是,在某些情况下,例如需要频繁创建和销毁对象或需要处理大量数据时,也可以使用 struct 来提高性能。
三、使用场景的建议
在 Unity 中,使用 struct 和 class 都有其优缺点和适用场景。下面是一些使用建议,帮助你在正确的情况下选择正确的类型。
- 对于 struct
1、适用于小型数据类型,例如向量、矩阵、颜色等。这些类型通常是不可变的,这意味着它们的值在创建后不会改变。
2、适用于需要高性能的场景,例如需要频繁创建和销毁对象或需要处理大量数据的场景。由于 struct 是值类型,它们在传递时会进行复制,这可能会导致性能问题,特别是在处理大量数据时。
3、适用于需要保证线程安全的场景。由于 struct 是不可变的,它们在多线程环境中可以安全地共享,而不需要使用锁或其他同步机制。
4、避免在 struct 中包含大量字段或数组。由于 struct 存储在栈上或在堆上的 value 类型对象中,它们的大小会直接影响内存使用率。
- 对于 class
1、适用于需要更复杂的数据组织和处理逻辑的场景,例如自定义组件和脚本等。由于 class 是引用类型,它们可以更好地利用 Unity 的引用类型机制。
2、适用于需要动态创建和销毁对象的场景,例如实例化预制体、管理游戏对象等。
3、适用于需要继承、多态和接口实现等面向对象编程的特性的场景。
4、避免过度使用继承和嵌套类型,这可能会导致代码过于复杂和难以维护。
总之,选择 struct 还是 class 取决于你的具体需求和场景。在实际开发中,应根据实际情况进行权衡和选择,以获得最佳性能和可维护性。
四、注意事项举例
- 在Linq的ForEach中使用时
using System;
using System.Collections.Generic;
using System.Linq;
public struct Item
{
public int Id;
public string Name;
}
public class ExampleClass
{
private List<Item> items = new List<Item>
{
new Item { Id = 1, Name = "Item 1" },
new Item { Id = 2, Name = "Item 2" },
new Item { Id = 3, Name = "Item 3" }
};
public void IterateList()
{
items.ForEach(item =>
{
Console.WriteLine($"Item ID: {item.Id}, Name: {item.Name}");
item.Name = null;//此处没有修改数据源,修改的传入的副本
});
}
}
同理,使用foreach是也一样。
下面代码中的item也只是struct的一个副本。
foreach (var item in items)
{
Console.WriteLine($"Item ID: {item.Id}, Name: {item.Name}");
}