我理解这个话题得到了很多回答。我的问题是针对它的说法或问题。
所以我说对了,用class关键字编写的代码将在托管堆上并且是一个引用类型,用struct编写的代码将在堆栈上并且是一个值类型?
答案 0 :(得分:6)
我曾经也是这样想的。但是,我最近与 Jon Skeet 进行了很好的讨论(他可能会提供更多详细信息),他向我解释说value type
也可以保留在堆上。关键是该变量的使用时间。如果它是一个短期值类型变量,它将只留在堆栈中。但是,如果它被多次使用,框架将把它保留在堆中以节省堆栈空间。
IMO,引用和值类型之间的关键区别在于将对象传递给另一个对象或方法。如果它是引用类型,您只需共享其引用。如果它是值类型,那么您制作它的副本。
关于短x长寿命变量的主题,这里是完整的图片:
在桌面CLR的Microsoft实现C#中,值类型 当值是局部变量或时,存储在堆栈中 临时的,不是lambda或的一个封闭的局部变量 匿名方法,方法体不是迭代器块,而且 抖动选择不注册该值。
来源:The Truth About Value Types(也在评论中)
答案 1 :(得分:0)
引用类型的任何存储位置(局部变量,参数,类字段,结构域或数组槽)将始终保持null
,否则将保留对堆上对象的引用。值类型的存储位置将保存该类型的所有公共和私有字段(原始值类型在内部存储为具有一个字段的结构,其被声明为具有相同的基本类型;一点点编译器魔法是用于识别何时必须使用特殊情况代码来处理该类型)。对于每个值类型,都有一个对应的堆对象类型,它具有相同的成员;尝试在引用类型存储位置存储值类型将创建适当堆类型的新堆对象,将value-type字段的内容复制到新对象的内容,并存储对该新对象的引用在请求的存储位置。这个过程叫做“拳击”。可以将盒装堆对象的字段的内容复制到值类型存储位置的内容,这个过程称为“拆箱”。请注意,因为使用引用类型存储位置访问盒装值类型,所以它们的行为类似于引用类型而不是类类型。 C#尝试假装值类型存储位置的类型和盒装值类型实例的类型是相同的类型,但这两种类型的行为有些不同;假装它们是相同的只会增加混乱。