代码之家  ›  专栏  ›  技术社区  ›  Sergio0694

sizeof(T)和Unsafe之间有什么区别。尺寸()?

  •  37
  • Sergio0694  · 技术社区  · 8 年前

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

    我知道关于 sizeof 操作员和 Marshal.SizeOf<T> 方法,我确实理解两者之间的区别。我说的是 SizeOf<T> 新中的方法 Unsafe

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

    这个 sizeof公司 操作员需要 类型名称 并返回 托管字节数 它应该在分配时占用(即 Int32 例如,将返回4)。

    这个 Unsafe.SizeOf<T> 另一方面,方法与中的所有其他方法一样,在IL中实现 不安全的 类,并查看代码,它的作用如下:

    .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 !!T 这与 sizeof(T) (调用 sizeof公司 类型名称为的运算符 T ),那么这两个词不是完全相等吗?

    此外,我看到该方法还分配了一个无用的对象( NonVersionableAttribute )在第一行中,这是否也会导致堆分配少量内存?

    我的问题是:

    可以肯定地说,这两种方法是完全等效的,因此使用经典方法更好吗 sizeof公司 运算符,因为这样也可以避免在 大小(&L);T> 方法是这个吗 大小(&L);T> 方法添加到 不安全的 现在上课只是为了方便吗?

    1 回复  |  直到 5 年前
        1
  •  29
  •   Evk    8 年前

    而这种方法实际上只是 sizeof IL指令-与常规指令不同 sizeof公司 运算符,因为此运算符不能应用于任意类型:

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

    枚举类型

    指针类型

    不包含任何 引用类型的字段或属性

    如果您尝试编写 Unsafe.SizeOf -它将不起作用:

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

    所以 不安全的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);                        
    }