Geo*_*kov 20 c# struct class immutability
以下是类与C#中的结构不同的唯一方法(如果我错了请纠正我):
假设我有一个不可变的结构,即包含初始化后无法修改的字段的结构.每次我将此结构作为参数传递或在赋值中使用时,该值都将被复制并存储在堆栈中.
然后假设我使这个不可变的结构成为一个不可变的类.此类的单个实例将创建一次,并且只有对类的引用将被复制到赋值和参数传递中.
如果对象是可变的,则这两种情况下的行为会有所不同:当一个人改变对象时,在第一种情况下,结构的副本将被修改,而在第二种情况下,原始对象将被改变.但是,在这两种情况下,对象都是不可变的,因此这个对象的用户实际上是类还是结构没有区别.
由于复制引用比复制struct便宜,为什么要使用不可变结构?
此外,由于可变结构是邪恶的,看起来根本没有理由使用结构.
我哪里错了?
Ree*_*sey 30
由于复制引用比复制struct便宜,为什么要使用不可变结构?
这并非总是如此.在64位操作系统上复制引用将是8个字节,这可能比许多结构更大.
另请注意,创建类可能更昂贵.创建结构通常完全在堆栈上完成(尽管有很多例外),这非常快.创建类需要创建对象句柄(用于垃圾收集器),在堆栈上创建引用以及跟踪对象的生命周期.这可能会增加GC压力,这也是一个真正的成本.
话虽这么说,创建一个大的不可变结构可能不是一个好主意,这是为什么在类和结构之间进行选择的指南建议总是使用类,如果你的结构将超过16个字节,如果它将被装箱,和其他使差异变小的问题.
话虽如此,我经常将我的决定更多地放在有关类型的预期用途和含义上.值类型应该用于引用单个值(同样,参考指南),并且通常具有语义含义和预期用法不同于类.在类或结构之间进行选择时,这通常与性能特征同样重要.
Eri*_*ert 23
里德的答案非常好,但只是增加几点:
如果我错了,请纠正我
你基本上走在正确的轨道上.您已经犯了将变量与值混淆的常见错误.变量是存储位置; 值存储在变量中.而你正在调整常见的神话,即"价值类型在堆栈上"; 相反,变量去任何短期或长期储存,因为变量的存储位置.变量是短期还是长期存储取决于其已知的寿命,而不是其类型.
但所有这些与你的问题并不特别相关,问题归结为要求驳斥这种三段论:
我们可以用几种方式驳斥三段论.
首先,是的,可变的结构是邪恶的.但是,它们有时非常有用,因为在某些有限的情况下,您可以获得性能优势.除非已经用尽其他合理途径并且存在真正的性能问题,否则我不推荐这种方法.
其次,引用复制不一定比结构复制便宜.引用通常实现为4或8字节的托管指针(尽管这是一个实现细节;它们可以实现为不透明的句柄).复制引用大小的结构既不比复制引用大小的引用更便宜也更昂贵.
第三,即使引用复制比结构复制便宜,也必须取消引用引用才能到达它们的字段.解除引用不是零成本!它不仅需要机器周期来取消引用引用,这样做可能会破坏处理器缓存,这可能使未来的解引用更加昂贵!
第四,即使参考复制比结构复制便宜,谁在乎呢?如果这不是产生不可接受的性能成本的瓶颈,那么哪一个更快就完全无关紧要.
第五,参考文献在内存空间中远比结构更昂贵.
第六,引用增加了费用,因为引用网络必须由垃圾收集器定期跟踪; 垃圾收集器可以完全忽略"blittable"结构.垃圾收集费用很高.
第七,与引用类型不同,不可变值类型不能为null.你知道每个价值都是一个很好的价值.正如Reed所指出的,为了获得引用类型的良好值,您必须运行分配器和构造函数.那不便宜.
第八,值类型代表值,程序通常是关于值的操纵.用一种语言"烘焙""价值"和"参考"的隐喻是有道理的,无论哪种"更便宜".