为啥 System.DateTime 结构的布局类型为 Auto?

Posted

技术标签:

【中文标题】为啥 System.DateTime 结构的布局类型为 Auto?【英文标题】:Why does the System.DateTime struct have layout kind Auto?为什么 System.DateTime 结构的布局类型为 Auto? 【发布时间】:2014-03-19 20:18:53 【问题描述】:

结构System.DateTime 及其表亲System.DateTimeOffset 将其结构布局类型设置为“自动”。这可以通过以下方式看到:

typeof(DateTime).IsAutoLayout    /* true */

或:

typeof(DateTime).StructLayoutAttribute.Value    /* Auto */

或者可以从声明的IL中看出:

.class public auto ansi serializable sealed beforefieldinit System.DateTime
              ¯¯¯¯

通常,使用 C# 编写的结构(即不是枚举的 .NET 值类型)将具有“顺序”布局(除非已应用 StructLayoutAttribute 来指定另一个布局)。

我搜索了一些常见的 BCL 程序集,DateTimeDateTimeOffset 是我发现的唯一公开可见的结构。

有人知道为什么DateTime 有这种不寻常的结构布局吗?

【问题讨论】:

有趣的事实。 Auto 上的文档说 运行时会自动为非托管内存中的对象成员选择适当的布局。使用此枚举成员定义的对象不能暴露在托管代码之外。尝试这样做会产生异常。 也许这仅用于强制在托管代码中使用。其原因可能是布局在 .NET 历史中多次更改(只是一个假设)。更多:msdn.microsoft.com/en-us/library/… auto 似乎还可以,也许问题应该是为什么其他类型很少使用它。 @ZoolWay 我也沿着这些思路思考。请注意,我们仍然可以在 C# 中使用 DateTime* 指针类型和 unsafe 上下文,例如这个程序可以正常工作:unsafe int[] memory = 123, 456, 789, 333, 666, 999, ; fixed (int* pointer = &memory[0]) var pointer2 = (DateTime*)pointer; Console.WriteLine(pointer2->DayOfWeek); pointer2 += 2; Console.WriteLine(pointer2->DayOfWeek); 【参考方案1】:

这需要推测,这个决定是在 很久 之前做出的,远在 .NET 1.0 发布之前。 System.DateTime 上的属性充其量只是一个微优化,在 .NET 代码中并不少见。这有点合适,结构只有一个字段,所以布局从来没有任何问题。内部 CustomAttribute 结构的那些可能是由同一个程序员完成的。也没关系,非托管代码永远不会看到它们。

System.DateTimeOffset 的那个是在很久以后才完成的,几乎可以肯定是一个复制粘贴错误。

那个程序员侥幸逃脱,CLR 没有理由从顺序版本重新安排布局。当结构包含足够大以容纳另一个小字段的字段之间的填充时,会使用自动布局进行重新排列。 DateTimeOffet 的情况并非如此。

当您为 DateTimeOffset 提交反馈报告时,您可能会让 Microsoft 专家注意这一点。这是错误的。将其发布到 connect.microsoft.com

【讨论】:

有趣。将考虑提交该错误报告。但是结构TimeSpanDateTime一样古老,它也只有一个实例字段,那么为什么这个“微优化”不适用于TimeSpan呢?你有什么想法吗? TimeSpan 是 [ComVisible(true)],不像 DateTime。 Submitted to Connect. 你确定DateTime 上的自动布局真的是无辜的,因为DateTime 只有一个字段吗?我希望您会在另一个线程中阅读an answer I just submitted,其中单字段结构(类似于DateTime)上的自动布局似乎传播到具有顺序布局的“复合”结构的布局。如果您知道这是否符合预期,也许您可​​以在那里发表评论。 当然,它不再尝试保持顺序。您可以在 SSCLI20 源代码 src/clr/vm/fieldmarshaler.cpp 中看到这一点,搜索“fDisqualifyFromManagedSequential”。

以上是关于为啥 System.DateTime 结构的布局类型为 Auto?的主要内容,如果未能解决你的问题,请参考以下文章

为啥我会在不应为 size 类安装的约束上收到自动布局错误?

C#常用函数

无法将类型为“System.DateTime”的对象强制转换为类型“System.String”

asp.net 无法将类型“System.DateTime”隐式转换为“string”

System.DateTime.Now 和 System.DateTime.Today 之间的区别

Android问题:自定义的布局类,一次Touch,两次调用onTouchEvent()方法,为啥?