sizeof(T)和Unsafe.SizeOf <T>()之间有什么区别?

Ser*_*694 32 .net c# cil visual-studio

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

我知道关于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
}
Run Code Online (Sandbox Code Playgroud)

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

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

我的问题是:

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

Evk*_*Evk 24

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

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

枚举类型

指针类型

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

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

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

因此Unsafe.SizeOf提升了sizeof运算符的限制,允许您使用sizeof任意类型的IL 指令(包括将返回引用大小的引用类型).

至于你在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);            
}
Run Code Online (Sandbox Code Playgroud)

另一个例子:

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);                        
} 
Run Code Online (Sandbox Code Playgroud)