.net net中的固定块

.net net中的固定块,.net,pointers,garbage-collection,fixed,unsafe,.net,Pointers,Garbage Collection,Fixed,Unsafe,我有点困惑什么时候需要固定块。我举了一个例子,下面是一个矛盾的场景: enum RoomType { Economy, Buisness, Executive, Deluxe }; struct HotelRoom { public int Number; public bool Taken; public RoomType Category; public void Print() { String status = Taken ?

我有点困惑什么时候需要固定块。我举了一个例子,下面是一个矛盾的场景:

enum RoomType { Economy, Buisness, Executive, Deluxe };

struct HotelRoom
{
    public int Number;
    public bool Taken;
    public RoomType Category;

    public void Print()
    {
        String status = Taken ? "Occupied" : "available";
        Console.WriteLine("Room {0} is of {1} class and is currently {2}", Number, Category, status);
    }
}
我制作了一个函数,它将指针指向
酒店房间

private unsafe static void Reserve(HotelRoom* room)
{
    if (room->Taken)
        Console.WriteLine("Cannot reserve room {0}", room->Number);
    else
        room->Taken = true;
}
在主要方法中,我有以下内容:

unsafe static void Main(string[] args)
{
    HotelRoom[] myfloor = new HotelRoom[4];
    for (int i = 0; i < myfloor.Length; i++)
    {
        myfloor[i].Number = 501 + i;
        myfloor[i].Taken = false;
        myfloor[i].Category = (RoomType)i;
    }
    HotelRoom Room =  myfloor[1];
    Reserve(&Room);   //I am able to do this without fixed block.
    //Reserve(&myfloor[1]);  //Not able to do this so have to use fixed block below. 

    fixed (HotelRoom* pRoom = &myfloor[1])
    {
        Reserve(pRoom);
    }

    myfloor[1].Print();
    Room.Print();
}
不安全的静态void Main(字符串[]args)
{
HotelRoom[]myfloor=新的HotelRoom[4];
对于(int i=0;i

我的困惑是我能做
预订(&Room)
,但不能
预订(&myfloor[1])
。我认为他们在做同样的事情——将
HotelRoom
结构的memeory地址传递给
Reserve
函数。为什么我需要
fixed
来执行此操作?

Room
是存储在堆栈中的局部变量,而
myfloor
存储在heap中。垃圾收集器可以移动堆中的对象来压缩它(地址会改变),所以需要“固定”它们。这就是为什么需要
fixed
语句的原因

更新:

此外,还有一种方法可以在堆栈上而不是堆上分配内存:

HotelRoom*fib=stackalloc HotelRoom[4]

在这种情况下,您不需要
fixed
语句


小圆盘:能够做到这一点并不意味着你当然应该这样做。正如其他人已经提到的,这是非常非.NET编写代码的方式,所以我认为这个问题是理论的。

< P>这只是一个丢弃的例子吗?< /P> 或者

我猜你是在试图把C++改写成C语言。您很少需要使用不安全的
,.NET的主要特点是它是一个托管框架

除非这里完全错了(所有代码都可以写为托管代码),否则您应该阅读非托管代码和托管代码之间的区别,尤其是如何编写C++背景下的C语言。 看看这些:


(编辑自)

明白了我完全没有抓住那一点。。你迫不及待地指了指。你猜写我也有C++ BRAGROND。我想知道我可以通过使用ref关键字来传递参数来实现这一点。在C#中,有时我们需要指针,我注意到的一个实例是。假设我想实现字符串反转,那么我能想到的只有我们使用系统;类测试{private unsafe static void Reverse(string text){fixed(char*pStr=text){char*pBegin=pStr;char*pEnd=pStr+text.Length-1;while(pBegin=t;}}}公共静态void Main(){string greet=“Hello World”;string x=“Hello World”;Reverse(greet);Console.WriteLine(greet);Console.WriteLine(x);}}}link给出了托管/非托管代码的好主意。我想知道,如果不建议使用无管理代码,为什么Microsoft将其保留在.Net framewrok中???
不安全
是因为它对性能非常有用(例如,使用指针沿长“字符串”迭代,而不必担心溢出检查,例如,CRC实现可以利用这一点)尤其是对于互操作(从.NET访问COM对象)来说,它通常是必需的。对于字符串反转,您只需向后迭代字符串,在运行时创建一个新的“StringBuilder”,不需要指针:)哦,在所有.NET代码下面,实际工作当然将在指针中完成。然而,托管框架对您隐藏了所有这些复杂性和潜在的错误。