C#结构体与类的区别
1.结构体和类一样 通过new方式初始化
如:
Coordinate c1 = new Coordinate() { x=1,y=2};
Coordinate c2 = new Coordinate(2,3);
也可以不使用New实例化
如:
Coordinate c3;
c3.x= 1;
c3.y = 1;
public struct Coordinate {
public int x;
public int y;
public Coordinate() {
}
public Coordinate(int x, int y)
{
this.x = x;
this.y = y;
}
public void print(){
Console.WriteLine($"坐标[{x},{y}]");
}
}
如:Coordinate c3;
c3.x= 1;
c3.print();
没有给y字段赋值 直接调用print()方法时,编译中报错 使用了未赋值的局部变量
也就是说 当我们在使用结构体时,一定要给 结构体所有的字段进行赋值 对象才被使用
Coordinate c1 = new Coordinate();
通过New方式实例化时,在给属性z赋值或者直接调用print()时 没有报错;
原因 当我们通过New方式进行实例化时,通过调用对应的构造函数,来给结构体的属性进行初始化,如int double类型字段默认是0,引用类型的字段默认null
结构体实例的内存在栈(stack)上进行分配,所占用的内存随声明它的类型或方法一起回收。 这就是在赋值时要复制结构体的一个原因。
相比之下,类实例的内存在堆(heap)上进行分配,当对类实例的所有引用都超出范围时,为该类实例分配的内存将由公共语言运行时自动回收(垃圾回收)。
2.结构体属于值类型 、类属性引用类型
Coordinate c2 = new Coordinate(2,3);
Coordinate c3;
c3 = c2;
c3.y = 6;
c2.print();//打印坐标[2,3]
c3.print();//打印坐标[2,6]
Console.ReadKey();
输出 c2打印坐标[2,3]。c3打印坐标[2,3] “c3” 的值是 “c2” 的副本,因此 “c2” 不受 “c3.y” 更改的影响。
但是在类中,输出 c2、c3打印坐标都是[2,6],因为变量 “c3” 和 “c2” 引用同一个对象。
结构体拷贝是拷贝对象的一个副本 ,所以修改副本不会对原有的对象产生影响
类拷贝是默认浅拷贝 引用的同一个地址 所以修改拷贝后的对象会对原有的对象产生影响
Coordinate c1 = new Coordinate(2, 3);
Coordinate c2;
c2.x = 2;
c2.y = 3;
Console.WriteLine(c1.Equals(c2));//true
打印的是true, 但是在类中打印的false
两个结构体实例的比较是基于值的比较,而类实例的比较则是对其引用的比较。
3.结构体不能继承于另一个结构体或者类,类也不能继承结构体。所有结构体都直接继承于抽象类 System.ValueType,System.ValueType 又继承于 System.Object。
4.结构体不能是基类,因此,结构体不能是 abstract 的,且总是隐式密封的(sealed)。
5.允许对结构体使用抽象(abstract)和密封(sealed)修饰符,也不允许对结构体成员使用 protected 或 protected internal 修饰符。
6.结构体中的函数成员不能是抽象的(abstract)或虚的(virtual),重写(override)修饰符只允许重写从 System.ValueType 继承的方法。
7.结构体可以和类一样实现接口
如
public interface ICoordinate {
void print();
}
public struct Coordinate: ICoordinate
{
public int x;
public int y;
public Coordinate() {
}
public Coordinate(int x, int y)
{
this.x = x;
this.y = y;
}
public void print()
{
Console.WriteLine($"坐标[{x},{y}]");
}
}
写下这篇 也是加深对结构体和类的区别上的理解吧 希望对大家有所帮助