繁体   English   中英

在C#中更改结构的大小是一个重大改变吗?

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM