簡體   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