C# class 和 struct的区别,以及如何把struct转换为引用类型

一般情况大家都使用类,但是Struct也是比较实用的一个类型,可能新手不知道他们有什么区别,我在这里总结了一下,方便新手学习,下面是我用.net Core 6写了一个demo

  1. 值类型虽然继承自ValueType,但是值类型的方法调用时会进行值类型拆装箱操作,因此性能上可能会有一些损耗。
  2. 值类型可以实现接口,通过实现接口可以为值类型添加一些行为和功能。例如,可以定义一个值类型的结构体,实现IComparable接口,来实现结构体之间的比较。
  3. 值类型是可以定义构造函数重载的,通过构造函数重载可以为值类型提供不同的构造方式。
  4. 值类型的内存分配和释放是由系统自动管理的,当值类型超出其作用域时,内存会立即被释放。
    而引用类型的内存管理是通过垃圾回收器进行的,当垃圾回收器判断某个对象不再被引用时,才会将其内存释放。

这个是一个房间类

public class Room
{
    public int RoomID { get; set; }

    public string RoomName { get; set; }
}

这个是人类


public class Person
{
    public int PersonID { get; set; }

    public string PersonName { get; set; }

    public Room Room  { get; set; }

    public void GetRoom(Room room) {
        room.RoomName = PersonName + "_" + room.RoomName;
        Room = room;
    }
}

这里person类做了一件事情就是,他拿到房间之后,通过GetRoom方法修改了房间名称,当然这样他只是为了给自己的房间起一个别名,但是这个做法已经影响原本房间的名称

//初始化房间
var room = new Room() { RoomName = "房间A", RoomID=1 };
Console.WriteLine("原始的room Name: "+room.RoomName);

var person = new Person() { PersonName = "张三", PersonID=110 };
//张三住进去给自己房间起来一个别名
person.GetRoom(room);
Console.WriteLine("Person room: "+person.Room.RoomName);
//影响了原本的房间名称,不能因为张三住了之后,房间名字就变成这个样子了
Console.WriteLine("修改后的 room: "+room.RoomName);

下面是运行输出结果:

想象,如果有李四,是不是他住了之后又会影响房间的名称呢,答案是:肯定会影响的

如果不想影响原本房间的名称需要怎么处理呢,很简单

把类改成结构问题就解决了

public struct Room
{
    public int RoomID { get; set; }

    public string RoomName { get; set; }
}

再次运行代码:

房间A,还是房间A,就算是李四住了之后(new person=‘李四’),还是房间A

--但是如果某天来了一个伟人,如果他住过之后,房间名称就得换名字,这个时候怎么办呢?可以通过ref方式改变

完整的代码如下:


public struct Room
{
    public int RoomID { get; set; }
    public string RoomName { get; set; }
}

public class Person
{
    public int PersonID { get; set; }
    public string PersonName { get; set; }

   //currentRoom 这个也是不能修改,如果currentRoom 和Room 修改就会数据导致不一致
    private Room currentRoom = new();
    //因为是伟人,所以这里特殊处理, ref  readonly 这里变量就不允许修改了
  public   ref  readonly Room Room { get { return ref currentRoom; } }

    public void GetRoom(ref Room room) {
        room.RoomName = PersonName + "_" + room.RoomName;
        currentRoom = room;
    }
}

//初始化房间
var room = new Room() { RoomName = "房间A", RoomID=1 };
Console.WriteLine("原始的room Name: "+room.RoomName);

var person = new Person() { PersonName = "黎明", PersonID=110 };
//黎明住进来之后,房间就有名气了,所以换名字了
person.GetRoom(ref room);
Console.WriteLine("Person room: "+person.Room.RoomName);
//黎明来了之后,之后房间就用黎明定义
Console.WriteLine("修改后的 room: "+room.RoomName);

运行之后输出结果如下,可以通过ref方式把值引用变成class引用 

important: Changing a type from a class to a struct can change the semantics of your program. When a class type is passed to a method, any mutations made in the method are made to the argument. When a struct type is passed to a method, and mutations made in the method are made to a copy of the argument. That means any method that modifies its arguments by design should be updated to use the ref modifier on any argument type you've changed from a class to a struct.

官网说的上面这段话,意思就是传递类,方法内改变参数值,会对原参数参数影响,而结构不会,

当传递结构的时候,传递的是结构的副本,所以不会对原参数产生影响

附上官网连接:Tutorial: Reduce memory allocations using struct data types and ref language features. - C# | Microsoft Learn

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值