Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/21.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/dart/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
为什么是可折叠的<;T>;C#7.2中的类是如何定义的?_C#_.net_Clr_Cil_C# 7.2 - Fatal编程技术网

为什么是可折叠的<;T>;C#7.2中的类是如何定义的?

为什么是可折叠的<;T>;C#7.2中的类是如何定义的?,c#,.net,clr,cil,c#-7.2,C#,.net,Clr,Cil,C# 7.2,我知道,Pinnable是新的Unsafe类中的方法使用的一个内部类,它不打算在该类之外的任何地方使用。这个问题不是关于一些实用的东西,但它只是为了理解为什么它被设计成这样,并学习更多关于这种语言及其各种“技巧”的知识 总而言之,定义了Pinnable类,如下所示: [StructLayout(LayoutKind.Sequential)] internal sealed class Pinnable<T> { public T Data; } [StructLayout(

我知道,
Pinnable
是新的
Unsafe
类中的方法使用的一个内部类,它不打算在该类之外的任何地方使用。这个问题不是关于一些实用的东西,但它只是为了理解为什么它被设计成这样,并学习更多关于这种语言及其各种“技巧”的知识

总而言之,定义了
Pinnable
类,如下所示:

[StructLayout(LayoutKind.Sequential)]
internal sealed class Pinnable<T>
{
    public T Data;
}
[StructLayout(LayoutKind.Sequential)]
内密封类可钉扎
{
公共数据;
}
它主要用于
Span.DangerousCreate
方法中:

publicstaticspan创建(objectobj,reft objectData,int-length)
{
可折叠可折叠=不安全的As(obj);
IntPtr byteOffset=Unsafe.byteOffset(ref pinnable.Data,ref objectData);
返回新跨距(pinnable、byteOffset、length);
}
Pinnable
的原因是它用于跟踪原始对象,以防
Span
实例是由一个实例(而不是本机指针)创建的

  • 如果引用类型在固定引用时并不重要(修复
    ref t
    不安全。因为(ref t)
    的工作原理相同),那么
    Pinnable
    类成为泛型类是否有具体原因?DotNetCross最初的设计实际上有一个
    Pinnable
    类,只有一个
    字节
    字段,它的工作原理是一样的。除了在编写/读取/返回引用时避免强制转换引用时间之外,在这种情况下使用泛型类是否有其他优势
  • 除了使用
    unsafe.As
    执行此unsafe cast之外,还有其他方法获取对对象的引用(我指的是对对象内容的引用,否则它将与类类型的任何变量相同)吗?我的意思是,任何获得对象引用的方法(首先应该基本上具有实际对象变量的相同地址,对吗?)都不必通过自定义的二级类
  • 首先,
    [StructLayout(LayoutKind.Sequential)]
    中的结构并不意味着它仅对结构有效,它意味着内存中字段的实际结构的布局,无论是在类中还是在值类型中。这控制数据的实际运行时布局,而不仅仅是类型封送到非托管代码的方式。顺序存储非常重要,因为如果没有顺序存储,运行时可以随意存储内存,这意味着数据之前可能会有一些填充

  • 从我对实现的理解来看,Pinnable的原因是允许创建一个Span实例到一个可以由GC移动的内存,而不必首先固定对象。如果您不使用实际的指针,而只使用引用,则根本不需要固定任何内容

    我注意到,它是在一个commit中引入的,描述中说它使Span更“可移植”(一个粗体的词,表示做了很多不安全的事情)。我想不出任何其他原因,除了与对齐有关的东西,为什么它是通用的。我想用一个
    T
    与另一个
    T
    的偏移量来表示
    T
    比用
    字节的偏移量来表示要好。第一个字段的类型可能在其实际地址中起作用,即使该类型标记为LayoutKind.Sequential

  • 对对象的引用不同于对对象的内部引用(对其数据的引用)。它是由实现定义的,但在.NET Framework中,任何类(或装箱值类型)的实例都以包含同步块(用于
    锁)和指向方法表的指针(也称为对象类型)的头开始。在32位上,头是8字节,但实际指针指向方法表的指针(出于性能原因,获取类型比锁定对象更频繁)

    因此,获取指向数据开头的指针的一种不可移植的方法是将对象引用强制转换为指针并向其添加4个字节。第一个字段应该从这里开始

    我能想到的另一种方法是利用。它通常用于访问数组或字符串数据,但也适用于其他对象:

    [StructLayout(LayoutKind.Sequential)]
    class Obj
    {
        public int A;
    }
    
    var obj = new Obj();
    var gc = GCHandle.Alloc(obj, GCHandleType.Pinned);
    IntPtr interior = gc.AddrOfPinnedObject();
    Marshal.WriteInt32(interior, 0, 16);
    Console.WriteLine(obj.A);
    
    我认为这实际上是非常可移植的,但仍然需要固定对象(GCHandle中定义了InternalAddRofPindedObject,但即使这没有检查句柄是否实际固定,如果在非固定对象上使用,返回值可能无效)

    尽管如此,Span使用的技术似乎是实现这一点的最方便的方法,因为许多底层工作都是在纯CIL(如参考算术)中完成的


  • Pinnable
    是默认使用
    LayoutKind.Auto
    的类(引用类型)<代码>顺序
    默认用于值类型(结构)。这就是为
    Pinnable
    指定布局的原因。请参阅中的备注部分。@YohDeadfall谢谢,我没有注意到有关使用该属性的类的详细信息!我已经编辑了问题,并将此信息添加到第二点。我不完全确定为什么需要这个属性,因为
    Span
    并没有显式地传递给非托管代码(我想,您是否可以修复它,获取一个指针并传递它?),但至少这个属性现在是有意义的,感谢详细的回答,即使
    pinted
    类的通用位仍然不是100%清楚,所有其他的都变得更有意义了,干杯!
    [StructLayout(LayoutKind.Sequential)]
    class Obj
    {
        public int A;
    }
    
    var obj = new Obj();
    var gc = GCHandle.Alloc(obj, GCHandleType.Pinned);
    IntPtr interior = gc.AddrOfPinnedObject();
    Marshal.WriteInt32(interior, 0, 16);
    Console.WriteLine(obj.A);