了解 C# 中的非托管关键字



>情况

我正在阅读有关 C# 7.x 到 8.0 中新增功能的 MSDN 文档,并找到了这些文章(doc1、doc2)

所以我决定创建一个小测试。

法典

指针.cs

internal readonly unsafe struct Pointer<T>
where T : unmanaged
{
private readonly void* mValue;
internal Pointer(T value)
{
//fixed (T* val = &value) <--- Error: You cannot use the fixed statement to take the adress of an already fixed expression.
//    mValue = val;
mValue = &value;
}
public static implicit operator Pointer<T>(T value)
{
return new Pointer<T>(value);
}
public static implicit operator string(Pointer<T> value)
{
var ptr = (T*)value.mValue;
return ptr->ToString(); // returns random values (maybe adresses).
}
}

程序.cs

class Program
{
static void Main(string[] args)
{
Pointer<int> ptr = 2;
Console.WriteLine(ptr); // prints random values (maybe adresses).
}
}

问题

为什么不允许我在构造函数中使用fixed语句。我的意思是这是有道理的,它抛出了一个错误。我已经说过T应该unmanaged,所以我认为它在内部自动使用fixed关键字。但是,如果确实如此,那么为什么我会得到随机值。

根据非托管类型的文档,T 将是某种不能包含对托管类型的引用的值类型。因此,它将在堆栈上分配。当构造函数返回时,堆栈将被弹出,指针将指向某个未定义的值。您不能将fixed用于堆栈上分配的内容,因为垃圾回收器无论如何都无法移动,因此被视为"固定"。

我对正在发生的事情的理解:

  1. 在这里,您可以获得堆栈中int的按值副本。

    internal Pointer(T value)
    
  2. 在这里,您将获取指向堆栈中int的指针。

    mValue = &value;
    
  3. 然后构造函数完成,int 从堆栈中弹出,指针是孤立的。

  4. 堆栈上放了其他东西,例如Pointer<T>结构本身,指针现在会导致垃圾。

    public static implicit operator string(Pointer<T> value)
    
  5. 您将垃圾视为int.

    var ptr = (T*)value.mValue;
    

最新更新