C# 类是引用类型,结构是值类型吗?

C# 类是引用类型,结构是值类型吗?,c#,class,struct,stack,heap,C#,Class,Struct,Stack,Heap,我知道这个问题有很多答案。我的问题是具体的方式说或问 所以我说的对吗,用class关键字编写的代码将位于托管堆上,是一种引用类型,而用struct编写的代码将位于堆栈上,是一种值类型?我以前也这样认为。然而,我最近与Jon Skeet进行了一次愉快的讨论(他可能会提供更多细节),他向我解释说,值类型也可能保留在堆上。关键是该变量将使用多长时间。如果它是一个短期值类型变量,它将只留在堆栈中。但是,如果它被多次使用,框架会将其保留在堆中以节省堆栈空间 在我看来,引用类型和值类型之间的关键区别在于将对

我知道这个问题有很多答案。我的问题是具体的方式说或问


所以我说的对吗,用class关键字编写的代码将位于托管堆上,是一种引用类型,而用struct编写的代码将位于堆栈上,是一种值类型?

我以前也这样认为。然而,我最近与Jon Skeet进行了一次愉快的讨论(他可能会提供更多细节),他向我解释说,
值类型也可能保留在堆上。关键是该变量将使用多长时间。如果它是一个短期值类型变量,它将只留在堆栈中。但是,如果它被多次使用,框架会将其保留在堆中以节省堆栈空间

在我看来,引用类型和值类型之间的关键区别在于将对象传递给另一个对象或方法。如果它是引用类型,您只需共享它的引用。如果它是一个值类型,那么您就是在复制它

关于短x长寿命变量的主题,以下是全图:

在桌面CLR上的C#的Microsoft实现中,值类型 当值是局部变量或 临时变量,它不是lambda或 匿名方法,并且方法体不是迭代器块,并且 抖动选择不注册该值


资料来源:(也在评论中)

我以前也是这样想的。然而,我最近与Jon Skeet进行了一次愉快的讨论(他可能会提供更多细节),他向我解释说,
值类型也可能保留在堆上。关键是该变量将使用多长时间。如果它是一个短期值类型变量,它将只留在堆栈中。但是,如果它被多次使用,框架会将其保留在堆中以节省堆栈空间

在我看来,引用类型和值类型之间的关键区别在于将对象传递给另一个对象或方法。如果它是引用类型,您只需共享它的引用。如果它是一个值类型,那么您就是在复制它

关于短x长寿命变量的主题,以下是全图:

在桌面CLR上的C#的Microsoft实现中,值类型 当值是局部变量或 临时变量,它不是lambda或 匿名方法,并且方法体不是迭代器块,并且 抖动选择不注册该值


Source:(它也在注释中)

引用类型的任何存储位置(局部变量、参数、类字段、结构字段或数组插槽)将始终保持
null
,否则将保持对堆上对象的引用。值类型的存储位置将保存该类型的所有公共和私有字段(基元值类型在内部存储为具有一个字段的结构,该字段声明为该基元类型;使用一点编译器魔法来识别何时必须使用特殊情况代码来处理该类型)。对于每个值类型,都有一个具有相同成员的对应堆对象类型;尝试将值类型存储在引用类型存储位置将创建相应堆类型的新堆对象,将值类型字段的内容复制到新对象的内容,并将对该新对象的引用存储在请求的存储位置。这个过程称为“装箱”。可以将装箱堆对象字段的内容复制到值类型存储位置的内容,这是一个称为“取消装箱”的过程。请注意,由于装箱的值类型是使用引用类型存储位置访问的,因此它们的行为类似于引用类型,而不是类类型。C#试图假装值类型存储位置的类型和装箱值类型实例的类型是相同的类型,但这两种类型的行为有所不同;假装它们是相同的只会增加混淆。

引用类型的任何存储位置(局部变量、参数、类字段、结构字段或数组插槽)将始终保持
null
,否则将保持对堆上对象的引用。值类型的存储位置将保存该类型的所有公共和私有字段(基元值类型在内部存储为具有一个字段的结构,该字段声明为该基元类型;使用一点编译器魔法来识别何时必须使用特殊情况代码来处理该类型)。对于每个值类型,都有一个具有相同成员的对应堆对象类型;尝试将值类型存储在引用类型存储位置将创建相应堆类型的新堆对象,将值类型字段的内容复制到新对象的内容,并将对该新对象的引用存储在请求的存储位置。这个过程称为“装箱”。可以将装箱堆对象字段的内容复制到值类型存储位置的内容,这是一个称为“取消装箱”的过程。请注意,由于装箱的值类型是使用引用类型存储位置访问的,因此它们的行为类似于引用类型,而不是类类型。C#试图假装值类型存储位置的类型和装箱值类型实例的类型是相同的类型,但这两种类型的行为有所不同;假装它们是相同的只会增加混淆。

值类型可以在堆栈上,但不一定要在堆栈上。不管怎样,这不是这里重要的外卖;重要的一点是,值类型在语义上表示一个值,而不是一个对值的引用。值类型并不总是驻留在堆栈上-请参见此处:询问不同的