sizeof(T)和Unsafe.SizeOf有什么区别 ()?

问题描述 投票:32回答:1

首先,在实际问题之前的一个小免责声明:

我知道有很多关于sizeof算子和Marshal.SizeOf<T>方法之间差异的闭合/重复问题,我确实理解了两者之间的区别。在这里,我在谈论新的SizeOf<T>课程中的Unsafe方法

所以,我不确定我是否理解这两个操作之间的实际区别,特别是在结构/类上使用该方法时是否存在特定的差异。

sizeof运算符采用类型名称并返回分配时应该占用的托管字节数(例如,Int32将返回4)。

另一方面,Unsafe.SizeOf<T>方法在IL中实现,就像Unsafe类中的所有其他方法一样,并且在这里查看代码是什么:

.method public hidebysig static int32 SizeOf<T>() cil managed aggressiveinlining
{
    .custom instance void System.Runtime.Versioning.NonVersionableAttribute::.ctor() = ( 01 00 00 00 )
    .maxstack 1
    sizeof !!T
    ret
}

现在,如果我没有错,代码只是调用sizeof !!Tsizeof(T)相同(调用类型名称为sizeofT运算符),那么它们中的两个是不是完全相同?

另外,我看到该方法也在第一行中分配了一个无用的对象(NonVersionableAttribute),所以这不会导致少量的内存被堆分配吗?

我的问题是:

是否可以肯定地说这两种方法是完全等价的,因此使用经典的sizeof算子更好,因为这也避免了在SizeOf<T>方法中分配该属性?为了方便起见,这个SizeOf<T>方法是否只是为了方便而添加到Unsafe类?

c# .net visual-studio cil
1个回答
23
投票

虽然这种方法确实只使用sizeof IL指令 - 但是与常规sizeof运算符存在差异,因为此运算符不能应用于任意类型:

用于获取非托管类型的字节大小。非托管类型包括下表中列出的内置类型,以及以下内容:

枚举类型

指针类型

用户定义的结构,不包含任何作为引用类型的字段或属性

如果你试着写Unsafe.SizeOf的模拟 - 它将无法工作:

public static int SizeOf<T>()
{
    // nope, will not compile
    return sizeof(T);
}

所以Unsafe.SizeOf解除了sizeof运算符的限制,允许你使用任意类型的IL sizeof指令(包括它将返回引用大小的引用类型)。

至于你在IL中看到的属性构造 - 这并不意味着将为每个调用实例化属性 - 这只是用于将属性与各种成员相关联的IL语法(在本例中为方法)。

例子:

public struct Test {
    public int Int1;
}

static void Main() {
    // works
    var s1 = Unsafe.SizeOf<Test>();
    // doesn't work, need to mark method with "unsafe"
    var s2 = sizeof(Test);            
}

另一个例子:

public struct Test {
    public int Int1;
    public string String1;
}


static unsafe void Main() {
    // works, return 16 in 64bit process - 4 for int, 4 for padding, because
    // alignment of the type is the size of its largest element, which is 8
    // and 8 for string
    var s1 = Unsafe.SizeOf<Test>();
    // doesn't work even with unsafe, 
    // cannot take size of variable of managed type "Test"
    // because Test contains field of reference type (string)
    var s2 = sizeof(Test);                        
} 
© www.soinside.com 2019 - 2024. All rights reserved.