[英]Is changing the size of a struct a breaking change in C#?
只是好奇,改变结构/值类型的大小是C#中的突破性变化? 结构在内存布局方面往往更敏感,因为更改它们会直接影响数组/其他结构的大小。 在使用的库中的结构布局发生变化之后,是否存在任何代码断开的示例(二进制或源代码)?
注意:通过“中断”,我的意思是它根本无法编译或IL无效。 例如,我不认为这是一个重大变化:
// My.Library v1
public struct MyStruct {}
// My.Library v2
public struct MyStruct { int _field; }
// App code
using My.Library;
using System.Runtime.InteropServices;
Console.WriteLine(Marshal.SizeOf<MyStruct>()); // before printed 1, now prints 4
因为它仍在运行
通过添加字段来改变大小对于严格管理的代码是可以的
添加字段是不间断的更改,因为代码将使用新类型重新进行JIT编辑,并且所有分配将使用正确的大小。 由于它是值类型,因此无论如何都将使用空值正确初始化新字段。
删除/更改现有字段或属性的类型肯定是一种变化。
值类型是密封的 - 因此没有其他库可以从该类型派生 - 所以与类不同,它们不能创建“此派生类没有实现新的虚拟属性/接口方法”的问题。
注意:如果值类型用于interop或控制之外的任何其他类型的二进制序列化,则任何更改都会中断。
即其他人使用MyLib.Point {int x;int y;}
将带有二进制序列化的点列表保存到文件中。 如果现在“MyLib”向MyLib.Point
添加新字段, MyLib.Point
不再能够使用二进制序列化读取序列化数据。 与本机互操作类似的问题。
是的,如果添加新字段,即使在严格管理的代码中,源代码不兼容也是可能的。 以您的示例为例,这将编译版本1但不编译版本2:
MyStruct s;
Console.WriteLine(s);
原因是如果为所有字段分配了值,C#允许使用struct local。 在版本1中,没有字段,因此s
是“明确分配”。 但是,如果在版本2中添加了一个字段,即使它是私有的,那么这也不再编译,因为s
不再是明确分配的。
这种情况应该是二进制兼容的,因为CLR保证字段初始化为其默认值。
Jared Parsons在结构中的私人领域有一篇很好的博客文章 ,其中详细说明了其他更改私有实施细节(对于不安全的代码)或破坏的情况。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.