一.相关概念说明:
Class和Struct在设计和使用时,会有不同的考虑因素。
Class适合表示复杂的对象和行为,会支持继承和多态性,而结构体则更适合表示轻量级数据和值类型,以提高性能并避免引用的管理开销。
类和结构有以下几个基本的不同点:
值类型 vs 引用类型:
- 结构是值类型(Value Type): 结构是值类型,它们在栈上分配内存,而不是在堆上。当将结构实例传递给方法或赋值给另一个变量时,将复制整个结构的内容。
- 类是引用类型(Reference Type): 类是引用类型,它们在堆上分配内存。当将类实例传递给方法或赋值给另一个变量时,实际上是传递引用(内存地址)而不是整个对象的副本。
继承和多态性:
- 结构不能继承: 结构不能继承其他结构或类,也不能作为其他结构或类的基类。
- 类支持继承: 类支持继承和多态性,可以通过派生新类来扩展现有类的功能。
默认构造函数:
- 结构不能有无参数的构造函数: 结构不能包含无参数的构造函数。每个结构都必须有至少一个有参数的构造函数。
- 类可以有无参数的构造函数: 类可以包含无参数的构造函数,如果没有提供构造函数,系统会提供默认的无参数构造函数。
赋值行为:
- 类型为类的变量在赋值时存储的是引用,因此两个变量指向同一个对象。
- 结构变量在赋值时会复制整个结构,因此每个变量都有自己的独立副本。
传递方式:
- 类型为类的对象在方法调用时通过引用传递,这意味着在方法中对对象所做的更改会影响到原始对象。
- 结构对象通常通过值传递,这意味着传递的是结构的副本,而不是原始结构对象本身。因此,在方法中对结构所做的更改不会影响到原始对象。
可空性:
- 结构体是值类型,不能直接设置为 null:因为 null 是引用类型的默认值,而不是值类型的默认值。如果你需要表示结构体变量的缺失或无效状态,可以使用 Nullable<T> 或称为 T? 的可空类型。
- 类默认可为null: 类的实例默认可以为
null
,因为它们是引用类型。
性能和内存分配:
- 结构通常更轻量: 由于结构是值类型且在栈上分配内存,它们通常比类更轻量,适用于简单的数据表示。
- 类可能有更多开销: 由于类是引用类型,可能涉及更多的内存开销和管理。
二.实例演示:
2.1实例界面:
2.2Class的定义&说明:
// 类声明
class MyClass
{
public int X;
public int Y;// 类可以有无参数的构造函数
public MyClass()
{
}// 有参数的构造函数
public MyClass(int x, int y)
{
X = x;
Y = y;
}// 类支持继承
// class MyDerivedClass : MyBaseClass
// {
// }
}
2.3Struct的定义&说明:
// 结构声明
struct MyStruct
{
public int X;
public int Y;// 结构不能有无参数的构造函数
// public MyStruct()
// {
// }// 有参数的构造函数
public MyStruct(int x, int y)
{
X = x;
Y = y;
}// 结构不能继承
// struct MyDerivedStruct : MyBaseStruct
// {
// }
}
2.4完整演示源码:
// 结构是值类型,分配在栈上
MyStruct MyStruct1 = new MyStruct(1, 2);
// 类是引用类型,分配在堆上
MyClass MyClass1 = new MyClass(3, 4);
private void test1()
{
MyStruct MyStruct2 = MyStruct1; // 复制整个结构
MyClass MyClass2 = MyClass1; // 复制引用,指向同一个对象
numericUpDown7.Value= MyStruct1.X;
numericUpDown8.Value = MyStruct2.X;
numericUpDown9.Value = MyClass1.X;
numericUpDown10.Value = MyClass2.X;
}
private void test2()
{
MyStruct MyStruct2 = MyStruct1; // 复制整个结构
MyClass MyClass2 = MyClass1; // 复制引用,指向同一个对象
// 修改结构实例不影响其他实例
MyStruct1.X = 5;
numericUpDown7.Value = MyStruct1.X;
numericUpDown8.Value = MyStruct2.X;
// Console.WriteLine($"Struct: {MyStruct1.X}, {MyStruct2.X}");
// 修改类实例会影响其他实例
MyClass1.X = 6;
numericUpDown9.Value = MyClass1.X;
numericUpDown10.Value = MyClass2.X;
}
private void button11_Click(object sender, EventArgs e)
{
test1();
}
private void button12_Click(object sender, EventArgs e)
{
test2();
}
// 结构声明
struct MyStruct
{
public int X;
public int Y;
// 结构不能有无参数的构造函数
// public MyStruct()
// {
// }
// 有参数的构造函数
public MyStruct(int x, int y)
{
X = x;
Y = y;
}
// 结构不能继承
// struct MyDerivedStruct : MyBaseStruct
// {
// }
}
// 类声明
class MyClass
{
public int X;
public int Y;
// 类可以有无参数的构造函数
public MyClass()
{
}
// 有参数的构造函数
public MyClass(int x, int y)
{
X = x;
Y = y;
}
// 类支持继承
// class MyDerivedClass : MyBaseClass
// {
// }
}