以下是代码:
trait EntityState
trait Transient extends EntityState
trait Persistent extends EntityState
trait Entity[State <: EntityState] {
def id(implicit ev: State <:< Persistent): Long
def persist(implicit ev: State <:< Transient): Entity[Persistent]
}
class Post[State <: EntityState] extends Entity[State] {
override def id(implicit ev: <:<[State, Persistent]): Long = 5
override def persist(implicit ev: <:<[State, Transient]): Post[Persistent] = new Post[Persistent]
}
// compiles
val x: Post[Persistent] = (new Post[Transient]).persist
// doesn't compile, as desired
// val y = (new Post[Persistent]).persist
助手代码:
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode, Pack = 4)]
public class STTEST
{
public DateTime DateTime;
}
static void Main(string[] args)
{
var st0 = new STTEST();
var bs0 = st0.ToBytes();
var st1 = bs0.ToObject<STTEST>();
}
编组操作正确,字节内容为零。 但是,编组操作返回st1.DateTime是“1899/12/30”。它应该是“0001/01/01”! 这是怎么回事? : - (
答案 0 :(得分:2)
Marshal.PtrToStructure()意图将结构内容转换为本机代码可以理解的表示形式。没有任何本机代码可以了解DateTime的外观。有多个“标准”,本机代码倾向于使用Unix时间戳(自1970年1月1日以来的秒数)或FILETIME(自1/1/1600以来100纳秒)或COM自动化日期(自12/30以来的浮动天数) / 1899)。
由于被迫在这些不兼容的标准之间做出选择,CLR设计人员在互操作代码(COM标准)中寻求最常见的表示。也显示为DateTime.To/FromOADate()。由于您未将DateTime保留为未初始化,因此它被强制转换为DATE的最低合法值,浮点值为0.因此转换为12/30/1899。
使用pinvoke marshaller将对象序列化为字节是一个iffy命题,对于像这样的意外结果具有非零赔率。你可能会因为没有让DateTime未初始化而在某种程度上取得领先。